题意:给你一个方阵,求左上角到右下角,求路经的数的乘积尾0最少是多少个,并输出路径。
dp求出2最少的路径和5最少的路径,再特殊处理一下0的情况。
#include <cstdio>
#include <string>
#include <queue>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <stack>
#include <cmath>
#define ll __int64
using namespace std;
#define pi acos(-1.0)
#define INF 0x3f3f3f3f
int ma[1005][1005][2];
int dp[1005][1005][2];
char path[1005][1005][2];
void dfs(int i,int x,int y)
{
if(path[x][y][i]==' ')
return;
if(path[x][y][i]=='R')
dfs(i,x,y-1);
else
dfs(i,x-1,y);
printf("%c",path[x][y][i]);
}
int main()
{
int n;
scanf("%d",&n);
for(int i=0; i<=n; i++)
for(int j=0; j<=n; j++)
for(int k=0; k<2; k++)
ma[i][j][k]=0,dp[i][j][k]=INF;
int xx=-1,yy=-1;
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
int x;
scanf("%d",&x);
if(x==0)
{
x=10;
xx=i;
yy=j;
}
while(x%2==0)
{
x/=2;
ma[i][j][0]++;
}
while(x%5==0)
{
x/=5;
ma[i][j][1]++;
}
}
}
dp[0][1][1]=dp[1][0][1]=dp[1][0][0]=dp[0][1][0]=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
for(int k=0;k<2;k++)
{
if(dp[i-1][j][k]+ma[i][j][k]<dp[i][j][k])
{
dp[i][j][k]=dp[i-1][j][k]+ma[i][j][k];
path[i][j][k]='D';
}
if(dp[i][j-1][k]+ma[i][j][k]<dp[i][j][k])
{
dp[i][j][k]=dp[i][j-1][k]+ma[i][j][k];
path[i][j][k]='R';
}
}
}
}
// cout<<xx<<" "<<yy<<endl;
path[1][1][1]=' ';
path[1][1][0]=' ';
if(xx!=-1)
{
if(dp[n][n][1]==0)
{
printf("%d\n",dp[n][n][1]);
dfs(1,n,n);
}
else if(dp[n][n][0]==0)
{
printf("%d\n",dp[n][n][0]);
dfs(0,n,n);
}
else
{
printf("1\n");
for(int i=1;i<yy;i++)
printf("R");
for(int j=1;j<n;j++)
printf("D");
for(int i=yy;i<n;i++)
printf("R");
}
}
else
{
if(dp[n][n][1]>dp[n][n][0])
{
printf("%d\n",dp[n][n][0]);
dfs(0,n,n);
}
else
{
printf("%d\n",dp[n][n][1]);
dfs(1,n,n);
}
}
puts("");
}