• Codeforces2B


    题目大意

    给定一个N*N的格子,每个格子里有一个非负数,要求你找出从左上角到右下角的一条路径,使得它满足路径上的格子里的数全部乘起来的积尾部0最少

    题解

    如果要产生0肯定是2*5得出来的,最终的乘积可以表示为2^x*5^y*C,那么零的个数就是min(x,y)。我们可以先对每个格子里的数预处理下,计算出2和5的个数来,然后DP分别求出2和5的最小个数然后选两者中的最小值,输出路径方法没啥说的,很传统~~还有一个要注意的问题就是如果某个格子的数字为0的情况,这个需要特殊判断一下,我们可以把它当做10,如果最后的结果0的个数大于1则直接输出尾部0的个数为1即可

    代码

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <string>
    #include <utility>
    using namespace std;
    #define  MAXN 1005
    #define  INF 0x7fffffff
    int path[MAXN][MAXN][2];
    int dp[MAXN][MAXN][2],a[MAXN][MAXN][2],n;
    int zerox,zeroy,x;
    string s;
    bool flag;
    int main()
    {
        scanf("%d",&n);
        flag=false;
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
            {
                scanf("%d",&x);
                if(!x)
                {     
                    a[i][j][0]=a[i][j][1]=1;
                    zerox=i,zeroy=j,flag=true;
                }
                else
                {
                    while(x%2==0) {a[i][j][0]++;x/=2;}
                    while(x%5==0) {a[i][j][1]++,x/=5;}
                }
            }
            for(int k=0;k<2;k++)
                for(int i=0;i<n;i++)
                    for(int j=0;j<n;j++)
                    {
                        int ans=INF;
                        if(i==0&&j==0) ans=0;
                        if(i!=0&&dp[i-1][j][k]<ans) ans=dp[i-1][j][k];
                        if(j!=0&&dp[i][j-1][k]<ans) ans=dp[i][j-1][k],path[i][j][k]=1;
                        dp[i][j][k]=ans+a[i][j][k];
                    }
                    int k=dp[n-1][n-1][0]<dp[n-1][n-1][1]?0:1;
                    if(flag&&dp[n-1][n-1][k]>1)
                    {
                        for(int i=0;i<zeroy;i++)
                            s+="R";
                        for(int i=0;i<zerox;i++)
                            s+="D";
                        for(int i=0;i<n-zeroy-1;i++)
                            s+="R";
                        for(int i=0;i<n-zerox-1;i++)
                            s+="D";
                        cout<<1<<endl<<s<<endl;
                    }
                    else
                    {
                        int i=n-1,j=n-1;
                        while(i>0||j>0)
                        {
                            if(path[i][j][k]==1)
                                s+="R",j--;
                            else
                                s+="D",i--;
                        }
                        reverse(s.begin(),s.end());
                        cout<<dp[n-1][n-1][k]<<endl<<s<<endl;
                    }
                    return 0;
    }
  • 相关阅读:
    字符串与Unicode码的相互转换
    关于es6中的yield
    ajax请求中的6个全局事件
    用H5上传文件
    类型化数组
    git笔记-9-29
    js正则表达式验证身份证号和密码
    assertThat用法
    java产生随机数的几种方式
    jQuery之Deferred对象详解
  • 原文地址:https://www.cnblogs.com/zjbztianya/p/3271449.html
Copyright © 2020-2023  润新知