题意:给一个n*m的矩阵,某些格子有垃圾。机器人从(1,1)出发到达(n,m)(n,m<=1e4),只能向下或者向右走,求最多能清理多少垃圾,和能清理最大数目垃圾的路径数,输出任意一条路径。
思路:LIS的变形。
有如下的细节需要注意:
1、为了保证下标唯一性,我们标记(i,j)为下标(i-1)*m+j-1; 最后输出路径时要+1。
2、标号后一定要排序!!!(WA了好多发)
3、若点(n,m)无垃圾,则要加入数组中并且标记,最后减去1。输出路径的时候也要判断一下。
4、判断上升的条件为 a[i]%m>=a[j]%m即可。(因为排序了)
5、注意输出格式。。。
另:虽然是1e4*1e4,不过O(n^2)的dp还是给过了,数据比较水。。。
代码:
#pragma comment(linker,"/STACK:102400000,102400000") #include<bits/stdc++.h> #define lson l,mid,t<<1 #define rson mid+1,r,t<<1|1 #define ll long long using namespace std; const int maxn=10010; const int inf=0x3f3f3f3f; int n,m,k; int ans,tmp,cnt[maxn],f; int a[maxn]; int dp[maxn]; int p[maxn]; bool flag; int ct; void dfs(int pos) { if(p[pos]!=-1) dfs(p[pos]); if(pos!=f||flag) {printf(" %d",a[pos]+1);} } int main() { int T,cas=1; while(scanf("%d %d",&n,&m)!=EOF) { if(n==-1&&m==-1) break; memset(cnt,0,sizeof(cnt)); f=0;flag=0; int x,y; while(scanf("%d %d",&x,&y)&&x&&y) { if(x==n&&y==m) flag=1; a[++f]=(x-1)*m+y-1; } sort(a+1,a+1+f); if(!flag) a[++f]=n*m-1; for(int i=1;i<=f;i++) { dp[i]=1; p[i]=-1; cnt[i]=1; for(int j=1;j<i;j++) if((a[i]%m)>=(a[j]%m)){ if((dp[i]<dp[j]+1)) { dp[i]=dp[j]+1; p[i]=j; cnt[i]=cnt[j]; } else if(dp[i]==dp[j]+1) { cnt[i]+=cnt[j]; } } } if(!flag) dp[f]--; printf("CASE#%d: %d %d",cas++,dp[f],cnt[f]); dfs(f); puts(""); } return 0; }