UVA - 10599 - Robots(II)(LIS变形输出任意路径)

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

猜你喜欢

转载自blog.csdn.net/lsd20164388/article/details/80374424