【Codeforces】CF 2 B The least round way(dp)

题目

传送门:QWQ

 

 

分析

求结尾0的数量QwQ。

10只能是$ 2 \times 5 $,我们预处理出每个数因子中2和5的数量。

我们接着dp出从左上到右下的经过的最少的2的数量和最少的5的数量。两者取min后就是答案。

特判数据中有0的情况,把他当做10处理。如果此时答案大于1,那么把答案更新成1。因为0只有1个0。

输出也有些小技巧 

 

代码

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1005;
 4 int a[maxn][maxn][2], dp[maxn][maxn][2];
 5 void print(int x,int y,int k,int state){
 6 
 7     if(x<=0 || y<=0) return;
 8     if(dp[x-1][y][k]==dp[x][y][k]-a[x][y][k]) print(x-1,y,k,0); 
 9     else print(x,y-1,k,1); 
10 
11     if(state==2) return;
12     if(state==1) putchar('R');
13     else putchar('D');
14 }
15 
16 int main(){
17     int n, posx, posy, flag=0;
18     scanf("%d",&n);
19     for(int i=1;i<=n;i++) {
20         for(int j=1;j<=n;j++) {
21             int num; scanf("%d",&num);
22             if(!num) {
23                 posx=i;posy=j; flag=1;
24                 a[i][j][0]=a[i][j][1]=1; continue;
25             }
26             while(num%2==0) a[i][j][0]++,num/=2;
27             while(num%5==0) a[i][j][1]++,num/=5;
28         }
29     }
30 
31     memset(dp,127,sizeof(dp));
32     dp[1][1][0]=dp[1][1][1] =0;
33     for(int i=1;i<=n;i++){
34         for(int j=1;j<=n;j++){
35             for(int k=0;k<2;k++){
36                 dp[i][j][k] = min (min(dp[i][j-1][k],dp[i-1][j][k]), dp[i][j][k]) + a[i][j][k];
37             }
38         }
39     }
40     int ans=min(dp[n][n][1],dp[n][n][0]);
41     if(flag && ans>1){
42         printf("%d\n",1);
43         for(int i=1;i<posx;i++) putchar('D');
44         for(int i=1;i<posy;i++) putchar('R');
45         for(int i=posx+1;i<=n;i++) putchar('D');
46         for(int i=posy+1;i<=n;i++) putchar('R');
47         return 0;
48     }
49     printf("%d\n",ans);
50     if(dp[n][n][1] > dp[n][n][0]) print(n,n,0,2);
51     else print(n,n,1,2);
52     return 0;
53 }

 

posted @ 2018-08-23 23:31  noble_(noblex)  阅读(234)  评论(0编辑  收藏  举报
/* */