点击链接:http://codeforces.com/problemset/problem/2/B
There is a square matrix n × n, consisting of non-negative integer numbers. You should find such a way on it that
- starts in the upper left cell of the matrix;
- each following cell is to the right or down from the current cell;
- the way ends in the bottom right cell.
Moreover, if we multiply together all the numbers along the way, the result should be the least "round". In other words, it should end in the least possible number of zeros.
The first line contains an integer number n (2 ≤ n ≤ 1000), n is the size of the matrix. Then follow n lines containing the matrix elements (non-negative integer numbers not exceeding 109).
In the first line print the least number of trailing zeros. In the second line print the correspondent way itself.
3 1 2 3 4 5 6 7 8 9
0 DDRR
题目大意:在矩阵中从左上角到右下角,只能向右走和向下走,把路径上的数都乘起来,求所得的积末尾的0最少的。要想能末尾形成0,那么必须是有2和5这两个质因子。把所有的数字都计算出他们的2和5的个数保存起来。在寻找一个路径包含的2或者5的数字最少的就是所求路径。
ps:首先想到的是dfs暴力求路径,但是无疑会超时,那么就要向dp上想了,这个很类似于数字三角形的dp,只不过是换成了矩阵的形式。从左上角到右下角做两次dp,一次是求2的,一次是求5的,两者取最小的dp结果。当然要首先处理一下边界。
情况2:如果矩阵中有0的话,那么所有的数乘以0都等于0,那么此时最多的末尾0的个数就是1。将等于0的dp初始为1,若在最后的结果中的dp大于1的话,那么就走有0的那条路径就可以了。dp的过程顺便记录路径方向
#include <iostream>
#include <cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int dp1[1005][1005];
int dp2[1005][1005];
char str1[1005][1005];
char str2[1005][1005];
char s[3000];
int n;
int main()
{
scanf("%d",&n);
int k;
int f=0;
int dx,dy;
for(int i=0; i<n; i++)
{
for(int j=0; j<n; j++)
{
scanf("%d",&k);
if(k==0)
{
dp1[i][j]=1;
dp2[i][j]=1;
f=1;
dx=i;
dy=j;
continue;
}
int a=0;
int b=0;
while(1)
{
if(k%2==0)
{
k=k/2;
a++;
}
else break;
}
while(1)
{
if(k%3==0)
{
k=k/3;
}
else break;
}
while(1)
{
if(k%5==0)
{
k=k/5;
b++;
}
else break;
}
dp1[i][j]=a;
dp2[i][j]=b;
}
}
// for(int i=0; i<n; i++)
// {
// for(int j=0; j<n; j++)
// {
// printf("%d ",dp[i][j]);
// }
// printf("\n");
// }
for(int i=1; i<n; i++)
{
dp1[i][0]+=dp1[i-1][0];
dp2[i][0]+=dp2[i-1][0];
str1[i][0]='D';
str2[i][0]='D';
}
for(int j=1; j<n; j++)
{
dp1[0][j]+=dp1[0][j-1];
dp2[0][j]+=dp2[0][j-1];
str1[0][j]='R';
str2[0][j]='R';
}
for(int i=1; i<n; i++)
{
for(int j=1; j<n; j++)
{
if(dp1[i-1][j]>dp1[i][j-1])
{
dp1[i][j]+=dp1[i][j-1];
str1[i][j]='R';
}
else
{
dp1[i][j]+=dp1[i-1][j];
str1[i][j]='D';
}
}
}
for(int i=1; i<n; i++)
{
for(int j=1; j<n; j++)
{
if(dp2[i-1][j]>dp2[i][j-1])
{
dp2[i][j]+=dp2[i][j-1];
str2[i][j]='R';
}
else
{
dp2[i][j]+=dp2[i-1][j];
str2[i][j]='D';
}
}
}
if(min(dp1[n-1][n-1],dp2[n-1][n-1])>=1&&f)
{
printf("1\n");
for(int i=0; i<dy; i++)
{
printf("R");
}
for(int i=1; i<n; i++)
{
printf("D");
}
for(int i=dy+1; i<n; i++)
{
printf("R");
}
printf("\n");
}
else
{
printf("%d\n",min(dp1[n-1][n-1],dp2[n-1][n-1]));
int x,y;
x=y=n-1;
int top=0;
if(dp1[n-1][n-1]<dp2[n-1][n-1])
{
while(1)
{
if(x==0&&y==0)break;
if(str1[x][y]=='D')
{
s[top++]='D';
x=x-1;
}
else
{
s[top++]='R';
y=y-1;
}
}
}
else
{
while(1)
{
if(x==0&&y==0)break;
if(str2[x][y]=='D')
{
s[top++]='D';
x=x-1;
}
else
{
s[top++]='R';
y=y-1;
}
}
}
for(int i=top-1; i>=0; i--)
{
printf("%c",s[i]);
}
printf("\n");
}
return 0;
}