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;
}
原文地址:https://www.cnblogs.com/zjbztianya/p/3271449.html