导航

codeforces 2B The least round way 【DP】

Posted on 2016-04-17 17:10  tun~  阅读(155)  评论(0编辑  收藏  举报

 VJ上可找到中文题意。

思路:

首先分解有多少2与多少5.接下来就是dp。

分两次,一次是根据2的数量贪心,另外一次是根据5的数量贪心,看哪一次乘积的末尾0最少。

需要注意的是两点:

1.输入有0的情况,要判断你的ans是不是大于1如果大于1那么输出一条经过0的路径即可。

2.当根据2的数量贪心进行dp的时候,如果可以转移的两个来源的2的数量是相同的,需要找到5的数量较小的状态转移过来。

代码较挫。

#include<bits/stdc++.h>
using namespace std;
int er[1005][1005],wu[1005][1005];
int dp[1005][1005],dpp[1005][1005];
bool from1[1005][1005],from2[1005][1005];
void print(bool p[][1005],int n){
    stack<int>s;
    int x=n-1,y=n-1;
    while(x!=0||y!=0){
        s.push(p[x][y]);
        if(p[x][y]==0)y--;
        else x--;
    }
    while(!s.empty()){
        int tmp=s.top();
        s.pop();
        if(tmp)printf("D");
        else printf("R");
    }
}
int main()
{
    int n;
    scanf("%d",&n);
    bool ok=0;
    int x,y;
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            int tmp;
            scanf("%d",&tmp);
            if(tmp==0){
                ok=1;
                x=i;y=j;
                continue;
            }
            while(tmp%2==0){
                tmp/=2;
                er[i][j]++;
            }
            while(tmp%5==0){
                tmp/=5;
                wu[i][j]++;
            }
        }
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            if(i==0){
                if(j!=0){
                    dp[i][j]=dp[i][j-1]+er[i][j];
                    dpp[i][j]=dpp[i][j-1]+wu[i][j];
                    from1[i][j]=0;
                }
                else{
                    dp[i][j]=er[i][j];
                    dpp[i][j]=wu[i][j];
                }
            }
            else{
                if(j!=0){
                    if(dp[i-1][j]<dp[i][j-1]){
                        dp[i][j]=dp[i-1][j]+er[i][j];
                        dpp[i][j]=dpp[i-1][j]+wu[i][j];
                        from1[i][j]=1;
                    }
                    else if(dp[i-1][j]==dp[i][j-1]){
                        if(dpp[i-1][j]<dpp[i][j-1]){
                            dp[i][j]=dp[i-1][j]+er[i][j];
                            dpp[i][j]=dpp[i-1][j]+wu[i][j];
                            from1[i][j]=1;
                        }
                        else{
                            dp[i][j]=dp[i][j-1]+er[i][j];
                            dpp[i][j]=dpp[i][j-1]+wu[i][j];
                            from1[i][j]=0;
                        }
                    }
                    else{
                        dp[i][j]=dp[i][j-1]+er[i][j];
                        dpp[i][j]=dpp[i][j-1]+wu[i][j];
                        from1[i][j]=0;
                    }
                }
                else{
                    dp[i][j]=dp[i-1][j]+er[i][j];
                    dpp[i][j]=dpp[i-1][j]+wu[i][j];
                    from1[i][j]=1;
                }
            }
        }
    }
    int ans=min(dp[n-1][n-1],dpp[n-1][n-1]);
    memset(dp,0,sizeof(dp));
    memset(dpp,0,sizeof(dpp));
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            if(i==0){
                if(j!=0){
                    dp[i][j]=dp[i][j-1]+wu[i][j];
                    dpp[i][j]=dpp[i][j-1]+er[i][j];
                    from2[i][j]=0;
                }
                else{
                    dp[i][j]=wu[i][j];
                    dpp[i][j]=er[i][j];
                }
            }
            else{
                if(j!=0){
                    if(dp[i-1][j]<dp[i][j-1]){
                        dp[i][j]=dp[i-1][j]+wu[i][j];
                        dpp[i][j]=dpp[i-1][j]+er[i][j];
                        from2[i][j]=1;
                    }
                    else if(dp[i-1][j]==dp[i][j-1]){
                        if(dpp[i-1][j]<dpp[i][j-1]){
                            dp[i][j]=dp[i-1][j]+wu[i][j];
                            dpp[i][j]=dpp[i-1][j]+er[i][j];
                            from2[i][j]=1;
                        }
                        else{
                            dp[i][j]=dp[i][j-1]+wu[i][j];
                            dpp[i][j]=dpp[i][j-1]+er[i][j];
                            from2[i][j]=0;
                        }
                    }
                    else{
                        dp[i][j]=dp[i][j-1]+wu[i][j];
                        dpp[i][j]=dpp[i][j-1]+er[i][j];
                        from2[i][j]=0;
                    }
                }
                else{
                    dp[i][j]=dp[i-1][j]+wu[i][j];
                    dpp[i][j]=dpp[i-1][j]+er[i][j];
                    from2[i][j]=1;
                }
            }
        }
    }
    if(ans>min(dp[n-1][n-1],dpp[n-1][n-1])){
        ans=min(dp[n-1][n-1],dpp[n-1][n-1]);
        if(ans>1&&ok){
            puts("1");
            for(int i=0;i<x;i++){
                printf("D");
            }
            for(int j=0;j<n-1;j++){
                printf("R");
            }
            for(int i=x;i<n-1;i++){
                printf("D");
            }
            return 0;
        }
        printf("%d\n",min(dp[n-1][n-1],dpp[n-1][n-1]));
        print(from2,n);
    }
    else{
        if(ans>1&&ok){
            puts("1");
            for(int i=0;i<x;i++){
                printf("D");
            }
            for(int j=0;j<n-1;j++){
                printf("R");
            }
            for(int i=x;i<n-1;i++){
                printf("D");
            }
            return 0;
        }
        printf("%d\n",ans);
        print(from1,n);
    }
}