【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 }