链接:http://codeforces.com/problemset/problem/2/B
题意:在一个棋盘上从左上角走到右下角,求经过点的乘积的结果尾数的0最少,要输出路径
题解:记录每个格子2和5的因子数,做两次dp,取较小的那个。有0的情况要特殊判断,可以把0当作10,最后的结果如果大于1,那么按照经过0来处理。记录路径记录前驱即可。但是不知道test 31为何wa了。。
#include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<stack> using namespace std; int n, a[1002][1002]; int num[1002][1002][2]; //0表示2因子个数,1表示5因子个数 int dp[1002][1002][2]; int path[1002][1002][2]; int mov[1002*1002]; int zx = -1, zy = -1; void output(int k){ /*if(i == 1 && j == 1){ return; } if(path[i][j][k] == 1){ output(i-1, j, k); printf("D"); } else{ output(i, j-1, k); printf("R"); }*/ int cnt = 0; int i = n, j = n; while(i!=1 || j!=1){ if(path[i][j][k] == 1){ mov[cnt++] = 1; i = i-1; } else{ mov[cnt++] = 0; j = j-1; } } for(int i = cnt-1; i>=0; i--){ if(mov[i] == 1) printf("D"); else printf("R"); } printf("\n"); } int main(){ scanf("%d", &n); for(int i = 1; i<=n; i++){ for(int j = 1; j<=n; j++){ scanf("%d", &a[i][j]); } } for(int i = 1; i<=n; i++){ for(int j = 1; j<=n; j++){ int temp = a[i][j]; if(a[i][j] == 0){ temp = 10; zx = i; zy = j; } while(temp%2 == 0){ num[i][j][0]++; temp/=2; } while(temp%5 == 0){ num[i][j][1]++; temp/=5; } } } /*for(int i = 1; i<=n; i++){ for(int j = 1; j<=n; j++){ cout<<num[i][j][0]<<"-"<<num[i][j][1]<<" "; } cout<<endl; }*/ for(int i = 1; i<=n; i++){ dp[1][i][0] = dp[1][i-1][0]+num[1][i][0]; path[1][i][0] = 0; dp[i][1][0] = dp[i-1][1][0]+num[i][1][0]; path[i][1][0] = 1; dp[1][i][1] = dp[1][i-1][1]+num[1][i][1]; path[1][i][1] = 0; dp[i][1][1] = dp[i-1][1][1]+num[i][1][1]; path[i][1][1] = 1; } for(int i = 2; i<=n; i++){ for(int j = 2; j<=n; j++){ dp[i][j][0] = min(dp[i-1][j][0], dp[i][j-1][0])+num[i][j][0]; path[i][j][0] = dp[i-1][j][0]>dp[i][j-1][0]?0:1; dp[i][j][1] = min(dp[i-1][j][1], dp[i][j-1][1])+num[i][j][1]; path[i][j][1] = dp[i-1][j][1]>dp[i][j-1][1]?0:1; } } int res; res = min(dp[n][n][0], dp[n][n][1]); int k = dp[n][n][0]>dp[n][n][1]?1:0; /*for(int i = 1; i<=n; i++){ for(int j = 1; j<=n; j++){ cout<<path[i][j][1]<<" "; } cout<<endl; } cout<<endl; for(int i = 1; i<=n; i++){ for(int j = 1; j<=n; j++){ cout<<dp[i][j][1]<<" "; } cout<<endl; }*/ if(zx!=-1){ printf("1\n"); for(int i = 1; i<zx; i++){ printf("D"); } for(int i = 1; i<=n; i++){ printf("R"); } for(int i = zx; i<n; i++){ printf("D"); } printf("\n"); } else{ printf("%d\n", res); output(k); } //cout<<dp[2][3][0]<<" "<<dp[3][3][1]<<endl; return 0; }