码迷,mamicode.com
首页 > 其他好文 > 详细

B. The least round way

时间:2021-04-05 12:16:09      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:最优   sync   type   air   name   printf   pair   mod   lin   

原题链接https://codeforces.com/problemset/problem/2/B

这题要特判矩阵里有0的情况,我就没特判,一直TLE(自己傻逼)

题意:给你一个矩阵,里面都是非负数,现在让你从\((1, 1)\)走到\((n, n)\), 并且把路径上的所有数乘起来,问你能得到的数末尾最少有多少个0。

思路:把路径上的每个数含有因子2和5的个数求出来(因为2和5才能凑出0),然后dp即可。注意特判有0的情况,如果矩阵有0,最后通常dp的答案\(>1\),那么经过0这个点能得到1这个最优解。

代码如下

#include<bits/stdc++.h>
#include<unordered_map>
#include<unordered_set> 
#include<iomanip>
#define IOS 	cin.tie(0), ios::sync_with_stdio(false) 
#define x first
#define y second

using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 1010, M = 1e5 + 10, mod = 1e9 + 7;
const double eps = 1e-12;
const double PI = acos(-1);

struct node{
	int a, b;
	char c;
};
pii f[N][N][2];		//一个是2的数目最少, 一个是5的数目最少 
node pre[N][N][2];
vector<char> v;


int main()
{
	int n, x;
	scanf("%d", &n);
	bool flag = false;
	int p, q;
	for(int i = 1 ; i <= n ; i ++)
		for(int j = 1 ; j <= n ; j ++)
		{
			scanf("%d", &x);
			if(x == 0)			//特判有0的情况 
			{
				flag = true;
				p = i, q = j;
				continue;
			}
			int a = 0, b = 0;
			while(x % 10 == 0) x /= 10, a ++, b ++;
			while(x % 2 == 0)  x /= 2, a ++;
			while(x % 5 == 0)  x /= 5, b ++;
			f[i][j][0] = f[i][j][1] = {a, b};
		}
	
	for(int i = 2 ; i <= n ; i ++)
	{
		f[i][1][0].x += f[i - 1][1][0].x;
		f[i][1][0].y += f[i - 1][1][0].y;
		pre[i][1][0] = {i - 1, 1, ‘D‘};	
		f[1][i][0].x += f[1][i - 1][0].x;
		f[1][i][0].y += f[1][i - 1][0].y;
		pre[1][i][0] = {1, i - 1, ‘R‘};
		
		f[i][1][1].x += f[i - 1][1][1].x;
		f[i][1][1].y += f[i - 1][1][1].y;
		pre[i][1][1] = {i - 1, 1, ‘D‘};	
		f[1][i][1].x += f[1][i - 1][1].x;
		f[1][i][1].y += f[1][i - 1][1].y;
		pre[1][i][1] = {1, i - 1, ‘R‘};
	 } 
	 
	 for(int i = 2 ; i <= n ; i ++)
	 	for(int j = 2 ; j <= n ; j ++)
	 	{
	 		if(f[i - 1][j][0].x < f[i][j - 1][0].x)
	 		{
	 			f[i][j][0].x += f[i - 1][j][0].x;
	 			f[i][j][0].y += f[i - 1][j][0].y;
	 			pre[i][j][0] = {i - 1, j, ‘D‘};
			 }
			 else
			 {
			 	f[i][j][0].x += f[i][j - 1][0].x;
			 	f[i][j][0].y += f[i][j - 1][0].y;
			 	pre[i][j][0] = {i, j - 1, ‘R‘};
			 }
			 
	 		if(f[i - 1][j][1].y < f[i][j - 1][1].y)
	 		{
	 			f[i][j][1].x += f[i - 1][j][1].x;
	 			f[i][j][1].y += f[i - 1][j][1].y;
	 			pre[i][j][1] = {i - 1, j, ‘D‘};
			 }
			 else
			 {
			 	f[i][j][1].x += f[i][j - 1][1].x;
			 	f[i][j][1].y += f[i][j - 1][1].y;
			 	pre[i][j][1] = {i, j - 1, ‘R‘};
			 }			 
		 }
	 
	int a = min(f[n][n][0].x, f[n][n][0].y), b = min(f[n][n][1].x, f[n][n][1].y);
	int res = min(a, b);
	if(flag && res > 1)
	{
		puts("1");
		for(int i = 1 ; i < p ; i ++)	putchar(‘D‘);
		for(int j = 1 ; j < n ; j ++)	putchar(‘R‘);
		for(int i = p ; i < n ; i ++)	putchar(‘D‘);
	}
	else
	{
		printf("%d\n", res);
		if(a < b)
		{
			auto t = pre[n][n][0];
			while(t.a != 0)
			{
				v.push_back(t.c);
				t = pre[t.a][t.b][0];
			}
		}
		else
		{
			auto t = pre[n][n][1];
			while(t.a != 0)
			{
				v.push_back(t.c);
				t = pre[t.a][t.b][1];
			}		
		}
		for(int i = v.size() - 1 ; i >= 0 ; i --)	putchar(v[i]);		
	}
	
	return 0;
}

B. The least round way

标签:最优   sync   type   air   name   printf   pair   mod   lin   

原文地址:https://www.cnblogs.com/luoyicong/p/14612900.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!