ICode9

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

Codeforces Round #787 (Div. 3)

2022-05-08 15:31:07  阅读:167  来源: 互联网

标签:787 int 路径 堆饼 Codeforces 数量 Div 节点 dp


比赛链接:

https://codeforces.com/contest/1675

F. Vlad and Unfinished Business

题目大意:

给定一棵 \(n\) 个节点的树,边权为 1,求出从点 \(x\) 出发,经过指定的 \(k\) 个点后,到达点 \(y\) 的最短路径长度。

思路:

如果不去其它点,那最短路径就是从 \(x\) 到 \(y\),通过一个数组记录下来,从父节点到子节点的路径为 1。
去往其它点的最短路径的起点一定是 \(x\) 到 \(y\) 的最短路径上的一个点,到了要去的点之后,回到起点,继续向目的地进发,也通过一个数组记录,从父节点到子节点的步数就为 2。
一遍 \(dfs\) 即可。

代码:

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int T, k, n, x, y;
bool work[N], to[N];
vector <int> g[N];
void init(){
	for (int i = 1; i <= n; i ++ ){
		work[i] = false;
		to[i] = false;
		g[i].clear();
	}
}
void dfs(int u, int fa){
	for (auto v : g[u]){
		if (v != fa){
			dfs(v, u);
			if (work[v])
				work[u] = true;
			if (to[v])
				to[u] = true;
		}
	}
}
void solve(){
	cin >> n >> k >> x >> y;
	init();
	for (int i = 1; i <= k; i ++ ){
		int j;
		cin >> j;
		work[j] = true;
	}
	to[y] = true;
	for (int i = 1; i < n; i ++ ){
		int u, v;
		cin >> u >> v;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	dfs(x, 0);
	int ans = 0;
	for (int i = 1; i <= n; i ++ ){
		if (i == x) continue;
		if (to[i]) ans ++ ;
		else if (work[i]) ans += 2;
	}
	cout << ans << "\n";
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	cin >> T;
	while (T -- )
		solve();
	return 0;
}

G. Sorting Pancakes

题目大意:

\(m\) 个饼,分成 \(n\) 堆排成一排,每一步操作可以将第 \(i(i > 1)\)堆的饼取出一个放到第 \(i - 1\) 堆中,或将第 \(j(j < n)\)堆的饼取出放到第 \(j + 1\) 堆中。问最少多少步可以让 \(n\) 堆饼的数量非递增

思路:

定义 \(dp[i][j][k]\) 为第 \(i\) 堆饼为 \(k\) 个,前 \(i\) 堆饼的数量总和为 \(j\) 个时让前 \(i\) 堆饼的数量非递增的最小移动次数
第 \(i\) 堆饼的数量要小于第 \(i - 1\) 堆饼的数量,所以枚举第 \(i - 1\) 堆饼的数量 \(x\)。
对于第 \(i\) 堆饼,因为前面 \(i - 1\) 堆已经排好了,那么它要将多余的饼移到后面去,或者将缺少的饼从后面移过来,所以先预处理一个前缀和,第 \(i\) 位的移动步数就是前缀和和 \(j\) 差值的绝对值。
可以得到转移方程 \(dp[i][j][k] = min(dp[i][j][k], dp[i - 1][j - k][x] + \lvert s[i] - j \rvert)\)。

参考:https://zhuanlan.zhihu.com/p/510066695

代码:

#include <bits/stdc++.h>
using namespace std;
const int N = 255;
int n, m, a[N], dp[N][N][N], ans = 1e9;
int main(){
	cin >> n >> m;
	memset(dp, 0x3f, sizeof dp);
	for (int i = 1; i <= n; i ++ ){
		cin >> a[i];
		a[i] += a[i - 1];
	}
	dp[0][0][m] = 0;
	for (int i = 1; i <= n; i ++ )
		for (int j = 0; j <= m; j ++ )
			for (int k = 0; k <= j; k ++ )
				for (int x = k; x <= m; x ++ )
					dp[i][j][k] = min(dp[i][j][k], dp[i - 1][j - k][x] + abs(a[i] - j));
	for (int j = 0; j <= m; j ++ )
		ans = min(ans, dp[n][m][j]);
	cout << ans << "\n";
	return 0;
}

标签:787,int,路径,堆饼,Codeforces,数量,Div,节点,dp
来源: https://www.cnblogs.com/Hamine/p/16242248.html

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

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

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

ICode9版权所有