ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【CF2B The least round way】题解

2021-12-22 17:34:33  阅读:160  来源: 互联网

标签:ch 结尾 题解 cell 觉定 way CF2B dp


题目链接

题目

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.

给定由非负整数组成的\(n \times n\) 的正方形矩阵,你需要寻找一条路径:

以左上角为起点

每次只能向右或向下走

以右下角为终点
并且,如果我们把沿路遇到的数进行相乘,积应当是最小“round”,换句话说,应当以最小数目的0的结尾.

思路

要使0结尾最少,也就是要使以2结尾和以5结尾最少,因为0的个数并不是由多的那个因子觉定的,而是由少的那个因子觉定的,所以我们可以看一下从起点到终点2和5最少出现多少次,取个min值就是答案,这个过程可以用dp来实现。

要注意的是,如果出现0,那么必然存在一条道路只有1个0结尾,这时我们就要与前面那种情况作比较,有更优的输出。

总结

一开始做这道题时想的是要把其中一个因子(也就是2或5)的个数压到dp转态中(就是 \(dp(i,j,k)\) 表示在 \((i,j)\) 号格子当5的个数为 \(k\) 时,2的个数最少为 \(dp(i,j,k)\)),类似一种dp的方法,这使我想不出怎么优化。

后来看题解,发现本质上0的个数是由2和5中较少那个数的数量觉定的,这个思路挺妙。其实对于这种题,尤其是背包累,当要存的转态多时,可以看看答案是否有小的那个数量觉定。

Code

#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;
ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+
(x<<3)+(ch^48);ch=getchar();}return x*f;}
//#define M
//#define mo
#define N 1010
int n, m, i, j, k; 
int a[N][N], dp[N][N][2], f[N][N][2], ans; 

void dfs(int x, int y, int k)
{
	// printf("%d %d %d\n", x, y, k); 
	// if(x==1||y==1) return ; 
	// if(x==1&&y==1) return ; 
	if(f[x][y][k]==1) dfs(x, y-1, k), putchar('R'); 
	if(f[x][y][k]==-1) dfs(x-1, y, k), putchar('D'); 
}

signed main()
{
//	freopen("tiaoshi.in", "r", stdin); 
//	freopen("tiaoshi.out", "w", stdout); 
	memset(dp, 0x3f, sizeof(dp)); 
	dp[0][1][0]=dp[0][1][1]=0; 
	ans=0x7fffffff; 
	n=read(); 
	for(i=1; i<=n; ++i)
		for(j=1; j<=n; ++j)	
		{
			a[i][j]=read(); 
			if(!a[i][j]) ans=1; 
			while(a[i][j]&&a[i][j]%2==0) a[i][j]/=2, ++m; 
			dp[i][j][0]=min(dp[i-1][j][0], dp[i][j-1][0])+m; m=0; 
			f[i][j][0]=(dp[i-1][j][0]<dp[i][j-1][0] ? -1 : 1); 
			while(a[i][j]&&a[i][j]%5==0) a[i][j]/=5, ++m; 
			dp[i][j][1]=min(dp[i-1][j][1], dp[i][j-1][1])+m; m=0; 
			f[i][j][1]=(dp[i-1][j][1]<dp[i][j-1][1] ? -1 : 1); 
			if(i==1&&j==1) f[i][j][0]=f[i][j][1]=0; 
			// printf("%lld %lld\n", dp[i][j][0], dp[i][j][1]); 
		}
	printf("%lld\n", min(ans, min(dp[n][n][0], dp[n][n][1]))); 
	if(ans<min(dp[n][n][0], dp[n][n][1]))
	{
		for(i=1; i<=n; ++i)
			for(j=1; j<=n; ++j)
				if(!a[i][j])
				{
					for(k=1; k<i; ++k) printf("D"); 
					for(k=1; k<j; ++k) printf("R"); 
					for(k=i; k<n; ++k) printf("D"); 
					for(k=j; k<n; ++k) printf("R"); 
					return 0; 
				}
	}
	if(dp[n][n][0]<dp[n][n][1]) dfs(n, n, 0); 
	else dfs(n, n, 1); 
	return 0; 
}

标签:ch,结尾,题解,cell,觉定,way,CF2B,dp
来源: https://www.cnblogs.com/zhangtingxi/p/15720399.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有