( ext{Solution:})
第一种想法:设 (dp[i][j][k]) 表示格子 ((i,j)) 尾数是 (k) 的最少零的个数,转移需要枚举尾数。
由于要输出路径,空间开不下而 GG .
第二种:考虑为什么会出现 (0:) 十进制下只有 (2,5) 相乘才可以。所以一个位置上最少的零的个数应该是 (minleft{Num_2,Num_5 ight})
于是考虑对这两个东西进行 dp 。设 (f[i][j]) 是到达格子 ((i,j)) 的最少 (2) 的个数, (g[i][j]) 对应 (5) 的个数。
那么对这两个东西进行转移即可。同时记录一下路径。
如果格子中有 (0) 的话,则答案必然不高于 (1) 特判一下即可。
#include<bits/stdc++.h>
using namespace std;
const int dyx=(1<<30);
int n,a[1001][1001];
int f[1001][1001],g[1001][1001];
int numt[1001][1001],numf[1001][1001];
int FG,F[1001][1001];
pair<int,int> pret[1001][1001],pref[1001][1001];
pair<int,int> pos0;
inline int Min(int x,int y) {
return x<y?x:y;
}
void print(pair<int,int> path,int t){
int fir=path.first;
int sec=path.second;
// printf("(%d %d)
",fir,sec);
if(fir==1&&sec==1)return;
if(t==1)print(pret[fir][sec],t);
else print(pref[fir][sec],t);
if(t==1){
if(pret[fir][sec].first<fir)printf("D");
else printf("R");
}
else{
if(pref[fir][sec].first<fir)printf("D");
else printf("R");
}
}
int main() {
freopen("CF2B.txt","r",stdin);
//f[i][j] g[i][j]
scanf("%d",&n);
for(int i=1; i<=n; ++i)
for(int j=1; j<=n; ++j) {
f[i][j]=g[i][j]=dyx;
scanf("%d",&a[i][j]);
if(a[i][j]==0)FG=1,pos0=make_pair(i,j),F[i][j]=1;
int cnt=0;
int x=a[i][j];
while(x%2==0&&x)cnt++,x/=2;
numt[i][j]=cnt;cnt=0;
while(x%5==0&&x)cnt++,x/=5;
numf[i][j]=cnt;cnt=0;
}
// for(int i=1;i<=n;++i)
// for(int j=1;j<=n;++j)
// printf("(%d %d)%c",numt[i][j],numf[i][j],j==n?'
':' ');
for(int i=0;i<=n;++i)
for(int j=0;j<=n;++j)
f[i][j]=g[i][j]=dyx;
f[1][1]=numt[1][1];
g[1][1]=numf[1][1];
for(int i=1; i<=n; ++i) {
for(int j=1; j<=n; ++j) {
if(i==1&&j==1)continue;
if(F[i][j])continue;
if(f[i-1][j]<f[i][j-1])pret[i][j]=make_pair(i-1,j);
else pret[i][j]=make_pair(i,j-1);
f[i][j]=Min(f[i-1][j],f[i][j-1])+numt[i][j];
if(g[i-1][j]<g[i][j-1])pref[i][j]=make_pair(i-1,j);
else pref[i][j]=make_pair(i,j-1);
g[i][j]=Min(g[i-1][j],g[i][j-1])+numf[i][j];
}
}
// for(int i=1;i<=n;++i)
// for(int j=1;j<=n;++j)
// printf("(%d %d)%c",f[i][j],g[i][j],j==n?'
':' ');
// puts("PathF:");
int ans=dyx;
// for(int i=1;i<=n;++i){
// for(int j=1;j<=n;++j){
// printf("(%d %d) ",pret[i][j].first,pret[i][j].second);
// }
// puts("");
// }
// puts("PathG:");
// for(int i=1;i<=n;++i){
// for(int j=1;j<=n;++j){
// printf("(%d %d) ",pref[i][j].first,pref[i][j].second);
// }
// puts("");
// }
ans=Min(ans,Min(f[n][n],g[n][n]));
if(!FG||(FG&&ans<=1)){
printf("%d
",ans);
if(f[n][n]<g[n][n]){
// if(pret[n][n].first<n)printf("R");
// else printf("D");
print(make_pair(n,n),1);
}
else {
// if(pref[n][n].first<n)printf("R");
// else printf("D");
print(make_pair(n,n),0);
}
puts("");
}
else {
puts("1");
for(int i=1;i<pos0.first;++i)printf("D");
for(int i=1;i<pos0.second;++i)printf("R");
for(int i=1;i<=n-pos0.first;++i)printf("D");
for(int i=1;i<=n-pos0.second;++i)printf("R");
puts("");
}
return 0;
}