思路
除了最终结果为0的情况,末尾出现的零只能来自2和5的乘积。可以通过动态规划求出到终点经过数包含2和5作为因数的次数分别是多少,两者中的最小值就是末尾0的数目。
考虑图中有0的情况,如果经过这个点那么最终结果必定只有一个0,因此对他单独处理,只有不走0得到的最优解为0的情况下才不从0上经过,否则就直接走0。
看了看网上题解,在打印答案时可以通过反向搜索来保证输出顺序正确,以及初始化的一个小细节。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int i=st;i<=ed;++i)
using namespace std;
const int N=1E3+10,INF=0x3f3f3f3f;
int n,dir,zero;
int f[N][N][2];
void dfs(int x,int y)
{
if(x==1 && y==1)
return;
if(f[x-1][y][dir]>f[x][y-1][dir])
{
dfs(x,y-1);
putchar('R');
}
else
{
dfs(x-1,y);
putchar('D');
}
}
int main()
{
cin>>n;
rep(i,2,n)
f[i][0][0]=f[i][0][1]=f[0][i][0]=f[0][i][1]=INF;
rep(i,1,n)
{
rep(j,1,n)
{
int k;
scanf("%d",&k);
if(k==0)
{
zero=i;
continue;
}
while(k%2==0)
{
++f[i][j][0];
k>>=1;
}
while(k%5==0)
{
++f[i][j][1];
k/=5;
}
rep(p,0,1)
{
if(f[i-1][j][p]<f[i][j-1][p])
f[i][j][p]+=f[i-1][j][p];
else
f[i][j][p]+=f[i][j-1][p];
}
}
}
dir=f[n][n][0]>f[n][n][1];
if(min(f[n][n][0],f[n][n][1])>1 && zero)
{
cout<<1<<endl;
rep(i,2,zero)
putchar('D');
rep(i,2,n)
putchar('R');
rep(i,zero+1,n)
putchar('D');
return 0;
}
cout<<min(f[n][n][0],f[n][n][1])<<endl;
dfs(n,n);
}