题目链接:

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;
}
posted on 2022-02-07 22:40  Hamine  阅读(30)  评论(0编辑  收藏  举报