题目链接:
https://codeforces.com/problemset/problem/2/B
题目大意:
非负整数组成的 \(n * n\) 的矩阵,从左上角出发,每一步只能往右或者往下走,走到右下角就结束,将路径上的所有数字乘起来,计算该数末尾的0的数量,找到一条路径,使得末尾0的数量最少。
思路:
乘数中 2,5 的数量决定了乘起来后在末尾形成 0 的数量,为了实现 0 数量最小,所以我们要找 2 的数量最小的路径和 5 数量最小的路径,做一个比较,这可以通过 \(dp\) 实现。
一条路径中 2 和 5 的数量的小的那个就是该路径最后末尾 0 的数量。但是有一个特殊情况,当有一个数是 0 的时候,后置 0 的数量就变成 1 了。
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10;
int a[N][N][3], b[N][N][3], n, num, f, p, q;
char ra[N][N], rb[N][N];
int cal(int a, int b){
int c = 0;
while (a % b == 0 && a > 0){
c++;
a /= b;
}
return c;
}
void print(int x, int y, int k){
if (x == 1 && y == 1) return;
if (k == 1){
if (rb[x][y] == 'D') print(x - 1, y, k);
else print(x, y - 1, k);
}
else {
if (ra[x][y] == 'D') print(x - 1, y, k);
else print(x, y - 1, k);
}
if (k == 1) cout << rb[x][y];
else cout << ra[x][y];
}
void solve(){
cin >> n;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++){
scanf("%d", &num);
if (num == 0) f = 1, p = i, q = j, a[i][j][0] = 1, b[i][j][0] = 1;
a[i][j][1] = cal(num, 2);
a[i][j][2] = cal(num, 5);
b[i][j][1] = cal(num, 2);
b[i][j][2] = cal(num, 5);
}
for (int i = 2; i <= n; i++){
ra[i][1] = 'D', rb[i][1] = 'D';
a[i][1][1] += a[i - 1][1][1];
a[i][1][2] += a[i - 1][1][2];
a[i][1][0] += a[i - 1][1][0];
b[i][1][1] += b[i - 1][1][1];
b[i][1][2] += b[i - 1][1][2];
b[i][1][0] += b[i - 1][1][0];
}
for (int j = 2; j <= n; j++){
ra[1][j] = 'R', rb[1][j] = 'R';
a[1][j][1] += a[1][j - 1][1];
a[1][j][2] += a[1][j - 1][2];
a[1][j][0] += a[1][j - 1][0];
b[1][j][1] += b[1][j - 1][1];
b[1][j][2] += b[1][j - 1][2];
b[1][j][0] += b[1][j - 1][0];
}
for (int i = 2; i <= n; i++)
for (int j = 2; j <= n; j++){
if (a[i - 1][j][1] > a[i][j - 1][1]){
ra[i][j] = 'R';
a[i][j][2] += a[i][j - 1][2];
a[i][j][0] += a[i][j - 1][0];
}
else{
ra[i][j] = 'D';
a[i][j][2] += a[i - 1][j][2];
a[i][j][0] += a[i - 1][j][0];
}
if (b[i - 1][j][2] > b[i][j - 1][2]){
rb[i][j] = 'R';
b[i][j][1] += b[i][j - 1][1];
b[i][j][0] += b[i][j - 1][0];
}
else{
rb[i][j] = 'D';
b[i][j][1] += b[i - 1][j][1];
b[i][j][0] += b[i - 1][j][0];
}
a[i][j][1] += min(a[i - 1][j][1], a[i][j - 1][1]);
b[i][j][2] += min(b[i - 1][j][2], b[i][j - 1][2]);
}
int mina = min(a[n][n][1], a[n][n][2]), minb = min(b[n][n][1], b[n][n][2]);
int t = min(mina, minb);
if (f && t > 1){
cout << "1\n";
for (int i = 2; i <= p; i++) cout << 'D';
for (int i = 1; i <= n - 1; i++) cout << 'R';
for (int i = p + 1; i <= n; i++) cout << 'D';
}
else {
if (mina > minb){
if (b[n][n][0]) cout << "1\n";
else cout << t << "\n";
print(n, n, 1);
}
else {
if (a[n][n][0]) cout << "1\n";
else cout << t << "\n";
print(n, n, 0);
}
}
}
int main(){
solve();
return 0;
}