The least round way
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.
Input
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).
Output
In the first line print the least number of trailing zeros. In the second line print the correspondent way itself.
Examples
Input |
3 1 2 3 4 5 6 7 8 9 |
Output |
0 DDRR |
题目大意
给定一个n×n的矩阵,以矩阵的左上单元格为起点,右下单元格为终点。求一条路径(只能向右或者向下延申),使这一条路径满足:所经单元格数字的乘积的后缀0最少。
输入格式
第一行输入整数n(2 ≤ n ≤ 1000)。
随后n行表示n×n矩阵的数值(0 ≤ ≤
)。
输出格式
第一行输出所求路径后缀0的个数。
第二行输出路径,用"D"表示向下,用"R"表示向右。
题目分析
1.如何让后缀0尽量少
假设路径乘积的结果为。
将这个数拆分成因子,可以得到至少个因子2和
个因子5.
且其中必有一个因子的个数与相同。
因此对于每个单元格中的数,我们需要求出包含因子2的个数和因子5的个数。
2.求后缀0的个数
设置数组.
用于存储
范围内因子2最少路径的因子2个数;
用于存储
范围内因子5最少路径的因子5个数.
递推公式为:
那么
是否就是后缀0的个数了?
不一定。
在test 31中的数据中,给出了包含0的数值。经过此单元格的路径乘积的后缀0均为1.
因此在有0且≥1的情况下,最后的结果均为1.
3.求出路径
在不包含0或者含0且<1的情况下,通过逆推
将结果存入字符串ans中。
否则输出一条经过0的路径。
AC代码
#include<bits/stdc++.h>
using namespace std;
int n,dp[1010][1010][2],t;
string ans;
//dp[i][j][0] 存因子2的个数, dp[i][j][0] 存因子5的个数
int main(){
scanf("%d",&n);
int flag=-1;//flag表示是否包含0
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
scanf("%d",&t);
if(t==0){
flag=i;
continue;
}
while(t%2==0){
t/=2;
dp[i][j][0]++;
}
while(t%5==0){
t/=5;
dp[i][j][1]++;
}
}
}
for(int i=1;i<n;i++){//对第一行和第一列进行处理
dp[i][0][0]+=dp[i-1][0][0];
dp[i][0][1]+=dp[i-1][0][1];
dp[0][i][0]+=dp[0][i-1][0];
dp[0][i][1]+=dp[0][i-1][1];
}
for(int i=1;i<n;i++){
for(int j=1;j<n;j++){
dp[i][j][0]+=min(dp[i-1][j][0],dp[i][j-1][0]);
dp[i][j][1]+=min(dp[i-1][j][1],dp[i][j-1][1]);
}
}
int res;//0表示因子2的个数少,1表示因子5的个数少
if(dp[n-1][n-1][0]<dp[n-1][n-1][1]){
res=0;
}
else res=1;
if(flag!=-1&&dp[n-1][n-1][res]){// 含0且min(dp[n-1][n-1][0],dp[n-1][n-1][1])>=1的情况
cout<<1<<endl;
for(int i=0;i<flag;i++){
cout<<"D";
}
for(int i=0;i<n-1;i++){
cout<<"R";
}
for(int i=flag;i<n-1;i++){
cout<<"D";
}
return 0;
}
int p1=n-1,p2=n-1;//逆推横坐标p1,纵坐标p2
while(p1&&p2){
if(dp[p1-1][p2][res]<dp[p1][p2-1][res]){
p1--;
ans="D"+ans;
}
else{
p2--;
ans="R"+ans;
}
}
while(p1){
ans="D"+ans;
p1--;
}
while(p2){
ans="R"+ans;
p2--;
}
cout<<dp[n-1][n-1][res]<<endl;
cout<<ans<<endl;
return 0;
}