CF2B The least round way

【题解】

  可以发现10的因数除了1和10之外只有2和5了,那么走过的路径上各个数字的2的因数个数之和、5的因数个数之和中较小的一个即是答案。这样的话DP即可。同时需要注意有0的情况,有0的时候有一个答案为1,要和前面求出的答案取较小值。

  1 #include<cstdio>
  2 #include<algorithm>
  3 #define LL long long
  4 #define rg register
  5 #define N 1010
  6 using namespace std;
  7 int n,m,px,py,tot,a[N][N],f[N][N],f2[N][N],exp2[N],exp5[N];
  8 bool flag=0;
  9 struct rec{
 10     int x,y;
 11 }from[N][N],from2[N][N];
 12 char ans[N<<2];
 13 inline int read(){
 14     int k=0,f=1; char c=getchar();
 15     while(c<'0'||c>'9') c=getchar();
 16     while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
 17     return k*f;
 18 }
 19 int main(){
 20     n=read(); exp2[0]=exp5[0]=1;
 21     for(rg int i=1;i<=25;i++) exp2[i]=exp2[i-1]<<1;
 22     for(rg int i=1;i<=13;i++) exp5[i]=exp5[i-1]*5;
 23     for(rg int i=1;i<=n;i++)
 24         for(rg int j=1;j<=n;j++){
 25             a[i][j]=read();
 26             if(!a[i][j]){
 27                 flag=1; px=i; py=j; continue;
 28             }
 29             int tmp=a[i][j];
 30             for(rg int k=25;k;k--) if(tmp%exp2[k]==0) f[i][j]+=k,tmp/=exp2[k];
 31             while(tmp%2==0) f[i][j]++;
 32             tmp=a[i][j];
 33             for(rg int k=13;k;k--) if(tmp%exp5[k]==0) f2[i][j]+=k,tmp/=exp5[k];
 34             while(tmp%5==0) f2[i][j]++;
 35 //            while(tmp%2==0){
 36 //                f[i][j]++;
 37 //                tmp>>=1;
 38 //            }
 39 //            tmp=a[i][j];
 40 //            while(tmp%5==0){
 41 //                f2[i][j]++;
 42 //                tmp/=5;
 43 //            }
 44         }
 45     for(rg int i=2;i<=n;i++) f[i][0]=f[0][i]=f2[i][0]=f2[0][i]=2e9;
 46 //    f[1][0]=f[0][1]=f2[1][0]=f2[0][1]=0;
 47     for(rg int i=1;i<=n;i++)
 48         for(rg int j=1;j<=n;j++){
 49             if(f[i-1][j]<f[i][j-1]){
 50                 from[i][j]=(rec){i-1,j};
 51                 f[i][j]+=f[i-1][j];
 52             }
 53             else{
 54                 from[i][j]=(rec){i,j-1};
 55                 f[i][j]+=f[i][j-1];
 56             }
 57         }
 58     for(rg int i=1;i<=n;i++)
 59         for(rg int j=1;j<=n;j++){
 60             if(f2[i-1][j]<f2[i][j-1]){
 61                 from2[i][j]=(rec){i-1,j};
 62                 f2[i][j]+=f2[i-1][j];
 63             }
 64             else{
 65                 from2[i][j]=(rec){i,j-1};
 66                 f2[i][j]+=f2[i][j-1];
 67             }
 68         }
 69     if(flag){
 70         if(min(f[n][n],f2[n][n])>1){
 71             puts("1");
 72             for(rg int i=2;i<=px;i++) putchar('D');
 73             for(rg int i=2;i<=py;i++) putchar('R');
 74             for(rg int i=px+1;i<=n;i++) putchar('D');
 75             for(rg int i=py+1;i<=n;i++) putchar('R');
 76             return 0;
 77         }
 78     }
 79     printf("%d\n",min(f[n][n],f2[n][n]));
 80     if(f[n][n]<f2[n][n]){
 81         int nx=n,ny=n;
 82         while(1){
 83             int fx=from[nx][ny].x,fy=from[nx][ny].y;
 84             if(fx==0||fy==0) break;
 85             if(fx<nx) ans[++tot]='D';
 86             else ans[++tot]='R';
 87             nx=fx; ny=fy;
 88             if(fx==1&&fy==1) break;
 89         }
 90     }
 91     else{
 92         int nx=n,ny=n;
 93         while(1){
 94             int fx=from2[nx][ny].x,fy=from2[nx][ny].y;
 95             if(fx==0||fy==0) break;
 96             if(fx<nx) ans[++tot]='D';
 97             else ans[++tot]='R';
 98             nx=fx; ny=fy;
 99             if(fx==1&&fy==1) break;
100         }
101     }
102     for(rg int i=tot;i;i--) putchar(ans[i]);
103 //    puts("");
104 //    for(rg int i=1;i<=n;i++){
105 //        for(rg int j=1;j<=n;j++) printf("[%d %d] ",from2[i][j].x,from2[i][j].y);
106 //        puts("");
107 //    }
108     return 0;
109 }
View Code

猜你喜欢

转载自www.cnblogs.com/DriverLao/p/9050598.html
way