CodeForces 2B The least round way

  原题传送: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 }
posted @ 2012-11-26 14:57  芒果布丁  阅读(525)  评论(0编辑  收藏  举报