VJ上可找到中文题意。
思路:
首先分解有多少2与多少5.接下来就是dp。
分两次,一次是根据2的数量贪心,另外一次是根据5的数量贪心,看哪一次乘积的末尾0最少。
需要注意的是两点:
1.输入有0的情况,要判断你的ans是不是大于1如果大于1那么输出一条经过0的路径即可。
2.当根据2的数量贪心进行dp的时候,如果可以转移的两个来源的2的数量是相同的,需要找到5的数量较小的状态转移过来。
代码较挫。
#include<bits/stdc++.h> using namespace std; int er[1005][1005],wu[1005][1005]; int dp[1005][1005],dpp[1005][1005]; bool from1[1005][1005],from2[1005][1005]; void print(bool p[][1005],int n){ stack<int>s; int x=n-1,y=n-1; while(x!=0||y!=0){ s.push(p[x][y]); if(p[x][y]==0)y--; else x--; } while(!s.empty()){ int tmp=s.top(); s.pop(); if(tmp)printf("D"); else printf("R"); } } int main() { int n; scanf("%d",&n); bool ok=0; int x,y; for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ int tmp; scanf("%d",&tmp); if(tmp==0){ ok=1; x=i;y=j; continue; } while(tmp%2==0){ tmp/=2; er[i][j]++; } while(tmp%5==0){ tmp/=5; wu[i][j]++; } } } for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ if(i==0){ if(j!=0){ dp[i][j]=dp[i][j-1]+er[i][j]; dpp[i][j]=dpp[i][j-1]+wu[i][j]; from1[i][j]=0; } else{ dp[i][j]=er[i][j]; dpp[i][j]=wu[i][j]; } } else{ if(j!=0){ if(dp[i-1][j]<dp[i][j-1]){ dp[i][j]=dp[i-1][j]+er[i][j]; dpp[i][j]=dpp[i-1][j]+wu[i][j]; from1[i][j]=1; } else if(dp[i-1][j]==dp[i][j-1]){ if(dpp[i-1][j]<dpp[i][j-1]){ dp[i][j]=dp[i-1][j]+er[i][j]; dpp[i][j]=dpp[i-1][j]+wu[i][j]; from1[i][j]=1; } else{ dp[i][j]=dp[i][j-1]+er[i][j]; dpp[i][j]=dpp[i][j-1]+wu[i][j]; from1[i][j]=0; } } else{ dp[i][j]=dp[i][j-1]+er[i][j]; dpp[i][j]=dpp[i][j-1]+wu[i][j]; from1[i][j]=0; } } else{ dp[i][j]=dp[i-1][j]+er[i][j]; dpp[i][j]=dpp[i-1][j]+wu[i][j]; from1[i][j]=1; } } } } int ans=min(dp[n-1][n-1],dpp[n-1][n-1]); memset(dp,0,sizeof(dp)); memset(dpp,0,sizeof(dpp)); for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ if(i==0){ if(j!=0){ dp[i][j]=dp[i][j-1]+wu[i][j]; dpp[i][j]=dpp[i][j-1]+er[i][j]; from2[i][j]=0; } else{ dp[i][j]=wu[i][j]; dpp[i][j]=er[i][j]; } } else{ if(j!=0){ if(dp[i-1][j]<dp[i][j-1]){ dp[i][j]=dp[i-1][j]+wu[i][j]; dpp[i][j]=dpp[i-1][j]+er[i][j]; from2[i][j]=1; } else if(dp[i-1][j]==dp[i][j-1]){ if(dpp[i-1][j]<dpp[i][j-1]){ dp[i][j]=dp[i-1][j]+wu[i][j]; dpp[i][j]=dpp[i-1][j]+er[i][j]; from2[i][j]=1; } else{ dp[i][j]=dp[i][j-1]+wu[i][j]; dpp[i][j]=dpp[i][j-1]+er[i][j]; from2[i][j]=0; } } else{ dp[i][j]=dp[i][j-1]+wu[i][j]; dpp[i][j]=dpp[i][j-1]+er[i][j]; from2[i][j]=0; } } else{ dp[i][j]=dp[i-1][j]+wu[i][j]; dpp[i][j]=dpp[i-1][j]+er[i][j]; from2[i][j]=1; } } } } if(ans>min(dp[n-1][n-1],dpp[n-1][n-1])){ ans=min(dp[n-1][n-1],dpp[n-1][n-1]); if(ans>1&&ok){ puts("1"); for(int i=0;i<x;i++){ printf("D"); } for(int j=0;j<n-1;j++){ printf("R"); } for(int i=x;i<n-1;i++){ printf("D"); } return 0; } printf("%d ",min(dp[n-1][n-1],dpp[n-1][n-1])); print(from2,n); } else{ if(ans>1&&ok){ puts("1"); for(int i=0;i<x;i++){ printf("D"); } for(int j=0;j<n-1;j++){ printf("R"); } for(int i=x;i<n-1;i++){ printf("D"); } return 0; } printf("%d ",ans); print(from1,n); } }