CF2B The least round way

原题网址: 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;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值