1 2 3 4

牛客提高 杀树

https://ac.nowcoder.com/acm/contest/5389/D

我也不敢说我学会了,说说总结的经验吧。

 

当假设dp[a][b],dp内部状态是小于等于b的时候,不必枚举b,只要让b尽可能大然后取dp[a][b] = min(dp[a][b-1],dp[a][b])就行了

 

应该就是这样了,代码方下来,以后多看几天

 

 

#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;
const int maxn = 5050 + 11;
typedef long long ll;

vector<int>G[maxn];
void add(int be, int en) {
	G[be].push_back(en);
}
ll dp[maxn][maxn];

int list[maxn];
int k;

int dfs(int x, int fa) {
	dp[x][0] = list[x];
	for (int s = 0; s < G[x].size(); s++) {
		int p = G[x][s];
		if (p == fa) continue;
		dfs(p, x);
		dp[x][0] += dp[p][k - 1];
	}

	for (int i = 1; i < k; i++) {
		ll tp = 0;
		for (int j = 0; j < G[x].size(); j++) {
			int p = G[x][j];
			if (p == fa) continue;
			dp[x][i] = min(dp[x][i] + dp[p][min(i - 1, k - i - 1)], dp[p][i - 1] + tp);

			tp += dp[p][min(i - 1, k - i - 1)];
		}
		dp[x][i] = min(dp[x][i], dp[x][i - 1]);
	}

	return 0;
}



int main() {
	int n;
	scanf("%d %d", &n, &k);
	for (int i = 1; i <= n; i++) {
		scanf("%d", &list[i]);
	}
	for (int i = 1; i < n; i++) {
		int be, en;
		scanf("%d %d", &be, &en);
		add(be, en);
		add(en, be);
	}
	dfs(1, -1);
	cout << dp[1][k - 1] << endl;
	return 0;
}

/*
6 3
1 2 3 4 5 6
1 2
2 5
3 5
5 6
6 4

输出5

*/

  

posted @ 2020-12-05 17:16  Lesning  阅读(77)  评论(0编辑  收藏  举报