给出一个矩阵,求从左上角到右下角找出一条路径,使得这条路径上的所有数的乘积后缀0最小。从左上角至右下角的输出路径。
1 #include <iostream> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <math.h> 5 #include <string.h> 6 #include <algorithm> 7 using namespace std; 8 const int maxn=1005; 9 int dp[maxn][maxn][4]; 10 int n,len; 11 char s[2*maxn]; 12 /** 13 解题思路: 14 0的个数是有2*5来决定的.对于每个数,质因子分解出2,5的个数。 15 找出2个数最小的路径l1上最后一个点的2的个数k 16 找出5个数最小的路径l2上最后一个点的5的个数m 17 对于l1来说,l2路径上最后一个点的2的个数会不小于k. 18 对于l2来说,l1路径上最后一个点的5的个数会不小于m. 19 所以要想使得后缀0最小,也就是min(k,m)最小的数就是解, 20 对应路径输出即可。 21 注意0的情况。 22 0不存在 直接输出路径 23 0存在,MIN>=1输出可行0路径 24 0存在,MIN<1输出路径 25 dp[i][j][0]从左上角到i,j点2的个数最小 26 dp[i][j][1]从左上角到i,j点5的个数最小 27 dp[i][j][2]到达2的方向 28 dp[i][j][3]到达5的方向 29 30 */ 31 void work(int k) 32 { 33 int x=n,y=n; 34 while(x>=1&&y>=1) 35 { 36 s[len++]=dp[x][y][k]; 37 if(dp[x][y][k]=='D') x=x-1; 38 else y=y-1; 39 if(x==1&&y==1) break; 40 } 41 } 42 int main() 43 { 44 int num,flag; 45 while(scanf("%d",&n)!=EOF) 46 { 47 flag=0; 48 memset(dp,0,sizeof(dp)); 49 for(int i=0; i<=n; i++) 50 { 51 dp[0][i][0]=dp[i][0][1]=dp[i][0][0]=dp[0][i][1]=99999999; 52 } 53 for(int i=1; i<=n; i++) 54 { 55 for(int j=1; j<=n; j++) 56 { 57 scanf("%d",&num); 58 if(num==0) flag=i; 59 while(num&&num%2==0) 60 { 61 dp[i][j][0]++; 62 num/=2; 63 } 64 while(num&&num%5==0) 65 { 66 dp[i][j][1]++; 67 num/=5; 68 } 69 if(i==1&&j==1) continue; 70 if(i==1&&j>1) 71 { 72 dp[i][j][2]=dp[i][j][3]='R'; 73 dp[i][j][0]+=dp[i][j-1][0]; 74 dp[i][j][1]+=dp[i][j-1][1]; 75 continue; 76 } 77 if(i>1&&j==1) 78 { 79 dp[i][j][2]=dp[i][j][3]='D'; 80 dp[i][j][0]+=dp[i-1][j][0]; 81 dp[i][j][1]+=dp[i-1][j][1]; 82 continue; 83 } 84 if(dp[i][j-1][0]<dp[i-1][j][0]) 85 { 86 dp[i][j][0]+=dp[i][j-1][0]; 87 dp[i][j][2]='R'; 88 } 89 else 90 { 91 dp[i][j][0]+=dp[i-1][j][0]; 92 dp[i][j][2]='D'; 93 } 94 if(dp[i][j-1][1]<dp[i-1][j][1]) 95 { 96 dp[i][j][1]+=dp[i][j-1][1]; 97 dp[i][j][3]='R'; 98 } 99 else 100 { 101 dp[i][j][1]+=dp[i-1][j][1]; 102 dp[i][j][3]='D'; 103 } 104 } 105 } 106 int ans5=dp[n][n][1],ans2=dp[n][n][0]; 107 len=0; 108 if(flag&&min(ans2,ans5)>=1)///没有考虑 存在0并且结果为0的情况 109 { 110 printf("1 "); 111 for(int i=1; i<flag; i++) printf("D"); 112 for(int i=1; i<n; i++) printf("R"); 113 for(int i=flag; i<n; i++) printf("D"); 114 printf(" "); 115 } 116 else 117 { 118 if(ans2<ans5) 119 { 120 printf("%d ",dp[n][n][0]); 121 work(2); 122 } 123 else 124 { 125 printf("%d ",dp[n][n][1]); 126 work(3); 127 } 128 for(int i=len-1; i>=0; i--) 129 printf("%c",s[i]); 130 printf(" "); 131 } 132 } 133 return 0; 134 }