dp[i][j]: 以i为根的子树花费为j时的最大收益。
dp[i][j] = max(dp[i][j],dp[i][j-k] + dp[son(i)][k])
#include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <algorithm> using namespace std; const int maxn = 111; int n,m; vector<int> son[maxn]; int bugs[maxn],val[maxn],cost[maxn]; bool vis[maxn]; int dp[maxn][maxn]; void dfs(int u) { vis[u] = true; for (int i = cost[u]; i <= m; ++i) dp[u][i] = val[u]; int size = son[u].size(); for (int i = 0; i < size; ++i) { int v = son[u][i]; if (vis[v]) continue; dfs(v); for (int j = m; j >= cost[u]; --j) { // k要从1开始 for (int k = 1; k + cost[u] <= j; ++k) dp[u][j] = max(dp[u][j],dp[u][j-k] + dp[v][k]); } } } int main() { while (scanf("%d %d",&n,&m)) { if (n == -1 && m == -1) break; int a,b; for (int i = 0; i < maxn; ++i) son[i].clear(); for (int i = 1; i <= n; ++i) { scanf("%d %d",&bugs[i],&val[i]); } for (int i = 1; i <= n; ++i) cost[i] = (bugs[i] + 19) / 20; for (int i = 1; i < n; ++i) { scanf("%d %d",&a,&b); son[a].push_back(b); son[b].push_back(a); } memset(vis,false,sizeof(vis)); memset(dp,sizeof(dp)); if(m == 0) // 这个判断要有 { printf("0\n"); continue; } dfs(1); printf("%d\n",dp[1][m]); } return 0; }