ICode9

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

Contest 2050 and Codeforces Round #718 (Div. 1 + Div. 2)题解

2021-04-24 03:01:27  阅读:229  来源: 互联网

标签:2050 cnt int 题解 ll cin ++ Div


题目链接

在B题上卡了一下,没排序debug半个小时,难受。

A题

题意:
给你一个n,定义2050乘以\(10^k\)(k取自然数)为"2050-number"
问你n最少是多少个"2050-number"的和

思路:
先判断\(n % 2050\)是否为0,然后答案就是\(n/2050\)的各位数之和。

ll n; 
 
int main()
{
    IOS;
	int T;
	cin >> T;
	while(T --)
	{
		cin >> n;
		ll res = 0;
		if(n % 2050 == 0)
			res += n / 2050;
		ll ans = 0;
		while(res)
		{
			ans += res % 10;
			res /= 10;
		}
		if(!ans) cout << -1 << endl;
		else cout << ans << endl;
	}
}

B题

题意:
让你组m条路径,每条路径的权重是路径上边的最小值,问你怎么可以让所有路径的权重之和最小。

思路:
将所有的边排序,每次拿出最小的边,然后其它边尽肯能拿大的即可。
显然这样可以留下更多小的边给其它路径。

ll n, m; 
int g[N][N];
pii cnt[N];
vector<int> v;
vector<int> ans[N];
 
int main()
{
    IOS;
	int T;
	cin >> T;
	while(T --)
	{
		v.clear();
		cin >> n >> m;
		for(int i = 0 ; i < n ; i ++)
		{
			for(int j = 0 ; j < m ; j ++)
				cin >> g[i][j], v.push_back(g[i][j]);	
			sort(g[i], g[i] + m);	
			cnt[i] = {0, m - 1};		
		}
		
		sort(v.begin(), v.end());
		for(int i = 0 ; i < m ; i ++)
		{
			int t = v[i];
			bool flag = false;
			for(int j = 0 ; j < n ; j ++)
			{
				if(g[j][cnt[j].x] == t && !flag)
				{
					ans[i].push_back(g[j][cnt[j].x ++]);
					flag = true;
				}
				else
				{
					ans[i].push_back(g[j][cnt[j].y --]);
				}
			}
		}
		
		for(int i = 0 ; i < n ; i ++)
		{
			for(int j = 0 ; j < m ; j ++)
				cout << ans[j][i] << " ";
			cout << "\n";			
		}
 
			
		for(int i = 0 ; i < m ; i ++)	ans[i].clear();
	}
}

C题

题意:
给你n个数,它们依次位于主对角线上的位置上,要求输出一个主对角线的下三角,使得对角线上每个数x都能连通和自己数值相等的数,并且有x个。

思路:
选择两个方向构造。我是依次处理每个对角线上的点,优先向左放,左边放不了再向下放。

ll n, m; 
int g[N][N];
 
int main()
{
    IOS;
	{
		cin >> n;
		for(int i = 1 ; i <= n ; i ++)	
			cin >> g[i][i];
		
		for(int i = 1 ; i <= n ; i ++)	
		{
			int d = g[i][i], cnt = g[i][i] - 1;
			int x = i, y = i;
			while(cnt)
			{
				if(y - 1 >= 1 && !g[x][y - 1])
				{
					g[x][y - 1] = d;
					cnt --;
					y = y - 1;
				}
				else
				{
					g[x + 1][y] = d;
					cnt --;
					x = x + 1;
				}				
			}
		}
		
		for(int i = 1 ; i <= n ; i ++)
		{
			for(int j = 1 ; j <= i ; j ++)
				cout << g[i][j] << " ";
			cout << endl;			
		}
 
	}
}

D题

题意:
给你一个网格图,问你从每个点出发,经过确定k步再回到该点的最小距离。

思路:
DP,f[i][j][k] 表示 点(i, j)经过k步回到该点的最短距离。

ll n, m, k; 
ll r[N][N], d[N][N];
ll f[N][N][21];
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};
 
int main()
{
    IOS;
	{
		cin >> n >> m >> k;
				
		for(int i = 1 ; i <= n ; i ++)
			for(int j = 1 ; j < m ; j ++)
				cin >> r[i][j];
 
		for(int i = 1 ; i < n ; i ++)
			for(int j = 1 ; j <= m ; j ++)
				cin >> d[i][j];
		
		memset(f, 0x3f, sizeof f);
		for(int i = 1 ; i <= n ; i ++)
			for(int j = 1 ; j <= m ; j ++)
				f[i][j][0] = 0;
		
		if((k & 1) == 0)
		{
			for(int p = 2 ; p <= k ; p += 2)	//总步数 
			{
				for(int q = 2 ; q <= p ; q += 2)	//转移步数 
				{
					for(int i = 1 ; i <= n ; i ++)
						for(int j = 1 ; j <= m ; j ++)
						{
							for(int w = 0 ; w < 4 ; w ++)
							{
								int x = i + dx[w], y = j + dy[w];
								if(x < 1 || x > n || y < 1 || y > m) continue;
								ll c;
								if(x < i) c = d[x][y];
								else if(x > i) c = d[i][y];
								else if(y < j) c = r[x][y];
								else c = r[x][j];
								
								f[i][j][p] = min(f[i][j][p], f[x][y][p - q] + q * c);
							}
						}
				}
			}
		}
		
		for(int i = 1 ; i <= n ; i ++)
		{
			for(int j = 1 ; j <= m ; j ++)
			{
				if(f[i][j][k] == 0x3f3f3f3f3f3f3f3f)
					cout << -1 << " ";
				else cout << f[i][j][k] << " ";
			}
			cout << "\n";			
		}
		
	}
}

标签:2050,cnt,int,题解,ll,cin,++,Div
来源: https://www.cnblogs.com/luoyicong/p/14696120.html

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

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

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

ICode9版权所有