题意:给一个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;
}