原题网址: DP - CF2B The least round way
题目描述
There is a square matrix n×nn×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 nn ( 2<=n<=10002<=n<=1000 ), nn is the size of the matrix. Then follow nn lines containing the matrix elements (non-negative integer numbers not exceeding 10^{9}109 ).
输出格式
In the first line print the least number of trailing zeros. In the second line print the correspondent way itself.
题意翻译
题目描述
给定由非负整数组成的n \times nn×n 的正方形矩阵,你需要寻找一条路径:
以左上角为起点
每次只能向右或向下走
以右下角为终点 并且,如果我们把沿路遇到的数进行相乘,积应当是最小“round”,换句话说,应当以最小数目的0的结尾.
输入格式
第一行包含一个整数 n (2 \leq n \leq 10002≤n≤1000),n 为矩阵的规模,接下来的n行包含矩阵的元素(不超过10^9的非负整数).
输出格式
第一行应包含最小尾0的个数,第二行打印出相应的路径(译注:D为下,R为右)
输入输出样例
输入 #1
3
1 2 3
4 5 6
7 8 9
输出 #1
0
DDRR
题解:
/*
https://www.luogu.com.cn/problem/CF2B
DP - CF2B The least round way
*/
#include<bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
int g[1005][1005][2];
// g[1005][1005][0] 记录该位置因子2个数
// g[1005][1005][1] 记录该位置因子5个数
int dp[1005][1005][2];
// dp[1005][1005][0] 记录到该位置2最小个数
// dp[1005][1005][1] 记录到该位置5最小个数
int n;
void PrintWay(int x, int y, int flag, int pos) {
if(x == 1 && y == 1) {
putchar(flag? 'D':'R');
return ;
}
if(x == 1) PrintWay(x, y-1, 0, pos);
else if(y == 1) PrintWay(x-1, y, 1, pos);
else if(dp[x][y][pos] == dp[x][y-1][pos] + g[x][y][pos]) PrintWay(x, y-1, 0, pos);
else PrintWay(x-1, y, 1, pos);
if(x!=n || y!=n) putchar(flag? 'D':'R');
}
int main() {
scanf("%d", &n);
int posx = -1;
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= n; j ++) {
int tmp;
scanf("%d", &tmp);
if(!tmp) { // 特判, 相当于该位置贡献一个2, 一个5, 相乘刚好一个尾 0
g[i][j][0] = g[i][j][1] = 1;
posx = i;
} else {
while(!(tmp%2)) { // 计算该位置因子2的个数
g[i][j][0] ++;
tmp /= 2;
}
while(!(tmp%5)) { // 计算该位置因子5的个数
g[i][j][1] ++;
tmp /= 5;
}
}
}
for(int k = 0; k < 2; k ++)
for(int i = 1; i <= n; i ++)
dp[i][0][k] = dp[0][i][k] = inf;
dp[1][1][0] = g[1][1][0];
dp[1][1][1] = g[1][1][1];
for(int k = 0; k < 2; k ++)
for(int i = 1; i <= n; i ++)
for(int j=i==1? 2:1; j <= n; j ++)
dp[i][j][k] = min(dp[i][j-1][k], dp[i-1][j][k]) + g[i][j][k];
int ans = min(dp[n][n][0], dp[n][n][1]);
int pos = dp[n][n][0] > dp[n][n][1]? 1 : 0;
if(posx!=-1 && ans>1) { // 经过0最少
cout << 1 << endl;
for(int i = 1; i < posx; i ++) putchar('D');
for(int i = 1; i < n; i ++) putchar('R');
for(int i = posx; i < n; i ++) putchar('D');
} else {
cout << ans << endl;
PrintWay(n, n, 0, pos);
}
return 0;
}