思路:
dp。
先算出每个数2因子的个数,和5因子的个数
因为要出现0那么要1个2乘1个5,那么最后的答案是min(2的个数,5的个数)
所以我们可以分开考虑,先算出使2最小的方案,再算出使5最小的方案,然后再取最小就可以了。
注意特判一种情况,如果经过一次0,那么答案只有1个0,再和上面那种情况比较一下,取个最小
mp[i][j][0]表示(i,j)这个位置2因子的个数
mp[i][j][1]表示(i,j)这个位置5因子的个数
状态:dp[i][j][0]表示到(i,j)这个位置2的最小个数
dp[i][j][1]表示到(i,j)这个位置5的最小个数
初始状态:dp[1][1][0]=mp[1][1][0]
dp[1][1][1]=mp[1][1][1]
目标状态:dp[n][n][0],dp[n][n][1]
状态转移:dp[i][j][s]=min(dp[i-1][j][s]+mp[i][j][s],dp[i][j-1][s]+mp[i][j][s])
代码:
#include<bits/stdc++.h> using namespace std; #define ll long long #define pb push_back #define mkp make_pair #define pii pair<int,int> #define mem(a,b) memset(a,b,sizeof(a)) const int N=1e3+5; int dp[N][N][2],mp[N][N][2]; pii pre[N][N][2]; void dfs(int x,int y,int s){ if(x==1&&y==1)return ; dfs(pre[x][y][s].first,pre[x][y][s].second,s); if(pre[x][y][s].first==x-1)cout<<‘D‘; else cout<<‘R‘; } int main(){ ios::sync_with_stdio(false); cin.tie(0); int n,T,ix,iy; cin>>n; bool f=false; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ cin>>T; if(T==0){ mp[i][j][0]=mp[i][j][1]=1; ix=i,iy=j; f=true; continue; } int t=0,tt=0; while(T%2==0){ T/=2; t++; } while(T%5==0){ T/=5; tt++; } mp[i][j][0]=t; mp[i][j][1]=tt; } } mem(dp,0x3f); for(int i=0;i<2;i++){ dp[1][1][i]=mp[1][1][i]; for(int j=1;j<=n;j++){ for(int k=1;k<=n;k++){ if(j==1&&k==1)continue; if(dp[j-1][k][i]+mp[j][k][i]<dp[j][k][i]){ dp[j][k][i]=dp[j-1][k][i]+mp[j][k][i]; pre[j][k][i]=mkp(j-1,k); } if(dp[j][k-1][i]+mp[j][k][i]<dp[j][k][i]){ dp[j][k][i]=dp[j][k-1][i]+mp[j][k][i]; pre[j][k][i]=mkp(j,k-1); } } } } //cout<<dp[n][n][0]<<‘ ‘<<dp[n][n][1]<<endl; int s,ans; if(dp[n][n][0]<dp[n][n][1])ans=dp[n][n][0],s=0; else ans=dp[n][n][1],s=1; if(f){ if(ans>1){ cout<<1<<endl; for(int i=0;i<ix-1;i++)cout<<‘D‘; for(int i=0;i<n-1;i++)cout<<‘R‘; for(int i=ix-1;i<n-1;i++)cout<<‘D‘; } else{ cout<<ans<<endl; dfs(n,n,s); } } else{ cout<<ans<<endl; dfs(n,n,s); } return 0; }