原题传送:http://codeforces.com/problemset/problem/2/B
动态规划。
要求经过的路径上的数的乘积的最少末尾0的个数,容易想到把“10”分解成“2”和“5”,那么答案就是“2”和“5”中计数少的那个。如果只用一次DP过程同时求解当前“2”或“5”的次数会发现前面出现的“2”或“5”的次数完全无法确定当前位置的值(这种类似贪心的算法是错误的)。那么可以想到将“2”和“5”两个数字分开,分别进行一次DP,题目要求的只是终点的值的末尾0的个数,那么答案就是终点值“2”和“5”中计数少的对应出现的次数。
对于矩阵中出现0的情况要特殊处理,看是否有一条路使得终值的末尾0的个数为0,是的话答案为0,打印出当前路径;否则,答案为1,打印出经过元素0的任一路径。
这道题通过数次提交发现:C++相对于g++来说,对数组越界情况会更严格一些。
View Code
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 #define FOR(i,s,t) for(int i=(s); i<(t); i++) 5 const int maxn = 1000 + 2; 6 7 int d2[maxn][maxn], d5[maxn][maxn], a[maxn][maxn], n, u, v; 8 char dr2[maxn][maxn], dr5[maxn][maxn]; 9 bool flag; 10 11 int cal(int x, int p) 12 { 13 if(x == 0) 14 return 1; 15 int cnt = 0; 16 while(x % p == 0) 17 { 18 cnt ++; 19 x /= p; 20 } 21 return cnt; 22 } 23 24 void DP(int d[][maxn], char dr[][maxn], int p) 25 { 26 FOR(i, 0, n) 27 d[0][i] = (i == 0 ? 0 : d[0][i-1]) + cal(a[0][i], p), dr[0][i] = 'R'; // 这里i == 0的情况要注意越界问题,不特判一下C++下会错,但g++能A 28 FOR(i, 1, n) 29 { 30 FOR(j, 0, n) 31 { 32 if(j == 0) 33 { 34 d[i][j] = d[i - 1][j] + cal(a[i][j], p); 35 dr[i][j] = 'D'; 36 } 37 else 38 { 39 if(d[i - 1][j] < d[i][j - 1]) 40 { 41 d[i][j] = d[i - 1][j] + cal(a[i][j], p); 42 dr[i][j] = 'D'; 43 } 44 else 45 { 46 d[i][j] = d[i][j - 1] + cal(a[i][j], p); 47 dr[i][j] = 'R'; 48 } 49 } 50 } 51 } 52 } 53 54 void printway(char dr[][maxn], int x, int y) 55 { 56 if(x == 0 && y == 0) 57 return ; 58 if(dr[x][y] == 'D') 59 printway(dr, x - 1, y); 60 else 61 printway(dr, x, y - 1); 62 putchar(dr[x][y]); 63 } 64 65 void read() 66 { 67 flag = false; 68 FOR(i, 0, n) 69 FOR(j, 0, n) 70 { 71 scanf("%d", &a[i][j]); 72 if(a[i][j] == 0) 73 { 74 flag = true; 75 u = i, v = j; 76 } 77 } 78 } 79 80 int main() 81 { 82 while(scanf("%d", &n) == 1) 83 { 84 read(); 85 DP(d2, dr2, 2); 86 DP(d5, dr5, 5); 87 if(flag) 88 { 89 if(d2[n - 1][n - 1] == 0) 90 { 91 printf("0\n"); 92 printway(dr2, n - 1, n - 1); 93 } 94 else if(d5[n - 1][n - 1] == 0) 95 { 96 printf("0\n"); 97 printway(dr5, n - 1, n - 1); 98 } 99 else 100 { 101 printf("1\n"); 102 FOR(i, 0, u) putchar('D'); 103 FOR(i, 0, n - 1) putchar('R'); 104 FOR(i, u, n - 1) putchar('D'); 105 } 106 } 107 else 108 { 109 if(d2[n-1][n-1] < d5[n-1][n-1]) 110 { 111 printf("%d\n", d2[n-1][n-1]); 112 printway(dr2, n - 1, n - 1); 113 } 114 else 115 { 116 printf("%d\n", d5[n-1][n-1]); 117 printway(dr5, n - 1, n - 1); 118 } 119 } 120 putchar('\n'); 121 } 122 return 0; 123 }