1. 程式人生 > 資訊 >4999/4499 元,華碩無畏 15 推出英特爾酷睿 i7-1260P、AMD 銳龍 R5-4600H 版本

4999/4499 元,華碩無畏 15 推出英特爾酷睿 i7-1260P、AMD 銳龍 R5-4600H 版本

題意:
給定一棵樹的關係,每個節點都有對應的體積和價值,限制規則是選擇一個節點是必須選擇它的父節點,給定總體積\(m\),問能獲得的最大的價值和是多少?

  • 看到是樹型結構我們可以思考樹形DP解決問題
  • 考慮以\(i\)節點為根的子樹,有這樣一個事實,想選擇它的子節點那它一定會被選擇,如果不選的話就是整棵數以它為根節點的子樹都沒得選了
  • 所以我們狀態設計為\(dp_{i,j}\)表示選擇以\(i\)為根的子樹總體積為\(j\)的情況下能獲得的最大價值和
  • 至此\(dfs\)一遍統計答案即可
#include <bits/stdc++.h>

using namespace std;

int n,m,root,fa[110],v[110],w[110],dp[110][110];

//dp[i][j]表示選擇以i節點為根的子樹 總體積不超過j的方案數 可知的是i節點一定要選 
//因為選子節點一定要選父節點 不選那子節點選不了 相當於一棵樹啥也不選

int head[110],tot,nxt[110],to[110];

void add(int u,int v) {
	to[++tot] = v,nxt[tot] = head[u],head[u] = tot;
}

void dfs(int u) {
	for(int i = v[u];i <= m;i ++) {//因為節點u一定要選 所以先初始化一下
		dp[u][i] = w[u];
	}
	for(int i = head[u];i;i = nxt[i]) {
		int son = to[i];
		dfs(son);
		for(int j = m;j >= v[u];j --) {
			for(int k = 0;k <= j - v[u];k ++) {//列舉分給子節點的體積
				dp[u][j] = max(dp[u][j],dp[u][j - k] + dp[son][k]);
			}
		}
	}
}

int main() {
	cin >> n >> m;
	for(int i = 1;i <= n;i ++) {
		cin >> v[i] >> w[i] >> fa[i];
		if(fa[i] == -1) {
			root = i;
			continue;
		}
		add(fa[i],i);
	}
	dfs(root);
	cout << dp[root][m] << '\n';
	return 0;
}