Codeforces 2B The least round way

The least round way

There is a square matrix n × 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.

Input

The first line contains an integer number n (2 ≤ n ≤ 1000), n is the size of the matrix. Then follow n lines containing the matrix elements (non-negative integer numbers not exceeding 109).

Output

In the first line print the least number of trailing zeros. In the second line print the correspondent way itself.

Examples

Input

3

1 2 3

4 5 6

7 8 9

Output

0

DDRR

 

题目大意

        给定一个n×n的矩阵,以矩阵的左上单元格为起点,右下单元格为终点。求一条路径(只能向右或者向下延申),使这一条路径满足:所经单元格数字的乘积的后缀0最少。

        输入格式

        第一行输入整数n(2 ≤ n ≤ 1000)。

        随后n行表示n×n矩阵的数值(0 ≤ a_{i,j} ≤ 10^{9})。

        输出格式

        第一行输出所求路径后缀0的个数。

        第二行输出路径,用"D"表示向下,用"R"表示向右。

题目分析

 1.如何让后缀0尽量少

        假设路径乘积的结果为k*10^{x}
        将这个数拆分成因子,可以得到至少x个因子2和x个因子5.
        且其中必有一个因子的个数与x相同。
        因此对于每个单元格中的数a_{i,j},我们需要求出包含因子2的个数和因子5的个数。

2.求后缀0的个数

        设置数组dp[i][j].
        dp[i][j][0]用于存储a_{0,0}-a_{i,j}范围内因子2最少路径的因子2个数;
        dp[i][j][1]用于存储a_{0,0}-a_{i,j}范围内因子5最少路径的因子5个数.
        递推公式为:
                dp[i][j][0]+=min(dp[i-1][j][0],dp[i][j-1][0]);
                dp[i][j][1]+=min(dp[i-1][j][1],dp[i][j-1][1]);
        那么
                min(dp[n-1][n-1][0],dp[n-1][n-1][1])
        是否就是后缀0的个数了?
        不一定。
        在test 31中的数据中,给出了包含0的数值。经过此单元格的路径乘积的后缀0均为1.
        因此在有0且min(dp[n-1][n-1][0],dp[n-1][n-1][1])≥1的情况下,最后的结果均为1.

3.求出路径
        
在不包含0或者含0且min(dp[n-1][n-1][0],dp[n-1][n-1][1])<1的情况下,通过逆推
将结果存入字符串ans中。
        否则输出一条经过0的路径。

AC代码

#include<bits/stdc++.h>
using namespace std;
int n,dp[1010][1010][2],t;
string ans;
//dp[i][j][0] 存因子2的个数, dp[i][j][0] 存因子5的个数
int main(){
	scanf("%d",&n);
	int flag=-1;//flag表示是否包含0 
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			scanf("%d",&t);
			if(t==0){
				flag=i;
				continue;
			}
			while(t%2==0){
				t/=2;
				dp[i][j][0]++;
			}
			while(t%5==0){
				t/=5;
				dp[i][j][1]++;
			}
		}
	}
	for(int i=1;i<n;i++){//对第一行和第一列进行处理 
		dp[i][0][0]+=dp[i-1][0][0];
		dp[i][0][1]+=dp[i-1][0][1];
		dp[0][i][0]+=dp[0][i-1][0];
		dp[0][i][1]+=dp[0][i-1][1];
	}
	for(int i=1;i<n;i++){
		for(int j=1;j<n;j++){
			dp[i][j][0]+=min(dp[i-1][j][0],dp[i][j-1][0]);
			dp[i][j][1]+=min(dp[i-1][j][1],dp[i][j-1][1]);
		}
	}
	int res;//0表示因子2的个数少,1表示因子5的个数少 
	if(dp[n-1][n-1][0]<dp[n-1][n-1][1]){
		res=0;
	}
	else res=1;

	if(flag!=-1&&dp[n-1][n-1][res]){// 含0且min(dp[n-1][n-1][0],dp[n-1][n-1][1])>=1的情况 
		cout<<1<<endl;
		for(int i=0;i<flag;i++){
			cout<<"D";
		}
		for(int i=0;i<n-1;i++){
			cout<<"R";
		}
		for(int i=flag;i<n-1;i++){
			cout<<"D";
		}
		return 0;
	}
	int p1=n-1,p2=n-1;//逆推横坐标p1,纵坐标p2 
	while(p1&&p2){
		if(dp[p1-1][p2][res]<dp[p1][p2-1][res]){
			p1--;
			ans="D"+ans;
		}
		else{
			p2--;
			ans="R"+ans;
		}
	}
	while(p1){
		ans="D"+ans;
		p1--;
	}
	while(p2){
		ans="R"+ans;
		p2--;
	}
	cout<<dp[n-1][n-1][res]<<endl;
	cout<<ans<<endl;
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值