CF 2B. The least round way【dp】

题目链接
思路
求所经过路径乘积结果为0的最少数目的路径。
假设已知所经过的路径以及每一个格子内的值,那么答案可以表示为\(ans = x_1*x_2*x_3*x_4...*x_n\),对每一个值进行质因子分解,那么答案数字对0的贡献仅有一种情况,即\(2*5=10\)这种情况。所以只要考虑从\((1,1)\)走到\((n,n)\)的路径上质因子\(2\)\(5\)数量更少的路径。
\(dp[i][j][x]:\)表示从\((1,1)\)走到\((i,j)\)的路径中,\(x\)出现的最少次数。
转移方向只要考虑从左边走过来还是往右边走过来即可。
转移方程:
\(dp[i][j][x]=min(dp[i-1][j][x],dp[i][j-1][x])+cnt[i][j][x]\)
\(cnt[i][j][x]:\)\(a[i][j]\)这个数字由几个\(x\)组成。
这边的x只要统计2和5即可。
特判一种情况,就是某一个格子内的数字为0的情况。这样的话答案为1,当且仅当\(min(dp[n][n][2],dp[n][n][5])>1\)的情况下考虑。
代码

#include<bits/stdc++.h>
using namespace std;

typedef long long LL;
typedef pair<int, int> PII;
const int N = 1000 + 10;
#define gcd __gcd
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;

int num[N][N][6];
int dp[N][N][6];
PII pos;

void print(int x, int y, int t) {
	if(x == 1 && y == 1) return;
	if(x > 1 && dp[x][y][t] == dp[x - 1][y][t] + num[x][y][t]) {
		print(x - 1, y, t);
		printf("D");
	}
	else {
		print(x, y - 1, t);
		printf("R");
	}
}

void solve() {
	int n;
	scanf("%d", &n);
	bool flag = false;

	for(int i = 2; i <= n; i++) {
		dp[0][i][2] = dp[0][i][5] = inf;
		dp[i][0][2] = dp[i][0][5] = inf;
	}

	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= n; j++) {
			int x;
			scanf("%d", &x);
			if(x == 0) {
				pos = {i, j};
				flag = true;
				continue;
			}
			while(x % 2 == 0) {
				num[i][j][2]++;
				x /= 2;
			}
			while(x % 5 == 0) {
				num[i][j][5]++;
				x /= 5;
			}
			dp[i][j][2] = min(dp[i - 1][j][2], dp[i][j - 1][2]) + num[i][j][2];
			dp[i][j][5] = min(dp[i - 1][j][5], dp[i][j - 1][5]) + num[i][j][5];
		}
	}
	if(flag && min(dp[n][n][2], dp[n][n][5]) > 1) {
		puts("1");
		for(int i = 1; i < pos.first; i++) {
			printf("D");
		}
		for(int i = 1; i < pos.second; i++) {
			printf("R");
		}
		for(int i = 1; i <= n - pos.first; i++) {
			printf("D");
		}
		for(int i = 1; i <= n - pos.second; i++) {
			printf("R");
		}
		return;
	}
	printf("%d\n", min(dp[n][n][2], dp[n][n][5]));
	if(dp[n][n][2] < dp[n][n][5]) print(n, n, 2);
	else print(n, n, 5);
}

int main() {
	// freopen("in.txt", "r", stdin);
	// int t; cin >> t; while(t--)
	solve();
	return 0;
}
posted @ 2021-05-06 18:01  这知识他不进我的脑子  阅读(37)  评论(0编辑  收藏  举报