• CF2B The least round way(dp+记录路径)


    B. The least round way
    time limit per test
    2 seconds
    memory limit per test
    64 megabytes
    input
    standard input
    output
    standard output

    There is a square matrix n × n, consisting of non-negative integer numbers. You should find such a way on it that

    • starts in the upper left cell of the matrix;
    • each following cell is to the right or down from the current cell;
    • the way ends in the bottom right cell.

    Moreover, if we multiply together all the numbers along the way, the result should be the least "round". In other words, it should end in the least possible number of zeros.

    Input

    The first line contains an integer number n (2 ≤ n ≤ 1000), n is the size of the matrix. Then follow n lines containing the matrix elements (non-negative integer numbers not exceeding 109).

    Output

    In the first line print the least number of trailing zeros. In the second line print the correspondent way itself.

    Examples
    input
    Copy

    3
    1 2 3
    4 5 6
    7 8 9

    output
    Copy

    0
    DDRR

    题意:给你一个n*n的矩阵 只能向下或者向右 问你从左上角走到左下角 你走过路径上数字的乘积尾部0个数最少的走法

    思路:我们知道只有2和5的组合可以让尾部为0 所以我们可以预处理每个数字有多少个2和5 然后很容易得出方程dp[i][j][0/1]=min(dp[i-1][j][0/1],dp[i][j-1][0/1])+a[i][j][0/1]

    值得注意的是 如果其中有出现0这个数字 那么就表示 只要经过这个点 那么尾部0的个数必然是1 那么答案就只能在0或者1中产生

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<string>
    #include<vector>
    #include<stack>
    #include<bitset>
    #include<cstdlib>
    #include<cmath>
    #include<set>
    #include<list>
    #include<deque>
    #include<map>
    #include<time.h>
    #include<queue>
    #define ll long long int
    using namespace std;
    inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    inline ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
    int moth[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
    int dir[4][2]={1,0 ,0,1 ,-1,0 ,0,-1};
    int dirs[8][2]={1,0 ,0,1 ,-1,0 ,0,-1, -1,-1 ,-1,1 ,1,-1 ,1,1};
    const int inf=0x3f3f3f3f;
    const ll mod=1e9+7;
    int dp[1007][1007][2]; //0表示2的个数  1表示5的个数 
    int a[1007][1007]; //存矩阵 
    bool f=0;
    struct node{
        int x;int y;
    };
    node path2[1007][1007]; //记录2的个数最少时的路径 
    node path1[1007][1007]; //记录5的个数最少时的路径 
    node ans[5007];
    int cnt=0;
    void output1(node x){ //记录答案 
        if(x.x==0&&x.y==0) return ;
        node t; t=path1[x.x][x.y];
        output1(t);
        ans[++cnt]=x;
    }
    void output2(node x){ //记录答案 
        if(x.x==0&&x.y==0) return ;
        node t; t=path2[x.x][x.y];
        output2(t);
        ans[++cnt]=x;
    }
    int main(){
        ios::sync_with_stdio(false);
        int n;
        cin>>n;
        int posx,posy;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++){
                cin>>a[i][j];
                int t=a[i][j];
                if(t==0){ //一但出现零我们需要标记一下 
                    f=1;
                    dp[i][j][0]++;
                    dp[i][j][1]++;
                    posx=i;
                    posy=j;
                    continue;
                }
                while(1){  //统计2 和 5 的个数 
                    if(t%2==0){
                        t/=2;
                        dp[i][j][0]++;
                    }else if(t%5==0){
                        t/=5;
                        dp[i][j][1]++;
                    }else{
                        break;
                    }
                }
            }
        for(int i=1;i<=n;i++){ // 预处理边界 
            dp[1][i][0]+=dp[1][i-1][0];
            dp[1][i][1]+=dp[1][i-1][1];
            node t; t.x=1; t.y=i-1;
            path1[1][i]=path2[1][i]=t;
            dp[i][1][0]+=dp[i-1][1][0];
            dp[i][1][1]+=dp[i-1][1][1];    
            t.x=i-1; t.y=1;
            path1[i][1]=path2[i][1]=t;
        }
        path1[1][1].x=path2[1][1].x=0;
        path1[1][1].y=path2[1][1].y=0;
        for(int i=2;i<=n;i++)
            for(int j=2;j<=n;j++){ //递推 
                if(dp[i-1][j][0]<dp[i][j-1][0]){
                    dp[i][j][0]=dp[i-1][j][0]+dp[i][j][0];
                    node temp; temp.x=i-1; temp.y=j;
                    path1[i][j]=temp;
                }else{
                    dp[i][j][0]=dp[i][j-1][0]+dp[i][j][0];
                    node temp; temp.x=i; temp.y=j-1;
                    path1[i][j]=temp;
                }
            }
        for(int i=2;i<=n;i++)
            for(int j=2;j<=n;j++){ //递推 
                if(dp[i-1][j][1]<dp[i][j-1][1]){
                    dp[i][j][1]=dp[i-1][j][1]+dp[i][j][1];
                    node temp; temp.x=i-1; temp.y=j;
                    path2[i][j]=temp;
                }else{
                    dp[i][j][1]=dp[i][j-1][1]+dp[i][j][1];
                    node temp; temp.x=i; temp.y=j-1;
                    path2[i][j]=temp;
                }
            }
        int minn=min(dp[n][n][0],dp[n][n][1]);
            if(minn>1&&f){ //表示尾部零最小的个数就是1 那么我们就可以直接输出 
                cout<<"1"<<endl;
                for(int i=1;i<posx;i++)
                    cout<<"D";
                for(int j=1;j<posy;j++)
                    cout<<"R";
                for(int i=posx;i<n;i++)
                    cout<<"D";
                for(int j=posy;j<n;j++)
                    cout<<"R";
                cout<<endl;
                   return 0;
            }
        cout<<minn<<endl;
        node e; e.x=n; e.y=n;
        if(dp[n][n][0]<dp[n][n][1])
            output1(e);
        else{
            output2(e);
        }
        for(int i=2;i<=cnt;i++){
            if(ans[i].x==ans[i-1].x+1)
                cout<<"D";
            else
                cout<<"R";
        }
        cout<<endl;
        return 0;
    } 
  • 相关阅读:
    PHP:__get()、__set()、__isset()、__unset()、__call()、__callStatic()六个魔术方法
    概念:RPG游戏中两个兵种互相攻击的逻辑
    php怎么获取checkbox复选框的内容?
    20150724之问题
    Uploadify 之使用
    oneThink后台添加插件步骤详解
    针对各种浏览器,前端解决方案(持续更新...)
    解决IE8中select下拉列表文字上下不居中的问题
    针对IE6 7 8当独写样式
    document对象详解
  • 原文地址:https://www.cnblogs.com/wmj6/p/10686423.html
Copyright © 2020-2023  润新知