题目链接
借此题了解树形dp思想
对于这个题目又称有树形依赖的背包问题,对于每个节点的抉择就是将其子节点看成几类,从这几类中选出<=最大体积的物品,实质是分组背包。因对于每一个物品,只有先选择了父节点,才可以被选中。所以有是一种树形结构。
下面是ac代码:
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <map>
#include <queue>
#include <stack>
#define ll long long
using namespace std;
const int N = 128;
vector<int> son[N];
int sor[N];
int f[N][N];
int n, m;
bool vis[N];
void init()
{
memset(vis, 0, sizeof(vis));
memset(f, 0, sizeof(f));
for (int i = 0; i < n; i++)
son[i].clear();
}
void dp(int x)
{
f[x][1] = sor[x];
vis[x] = 1;
int si = son[x].size();
for (int i = 0; i < si; i++)
{
int t = son[x][i];
if (vis[t]) continue;
dp(t);
for (int j = m; j > 0; j--)
{
for (int k = 1; k < j; k++)
{
f[x][j] = max(f[x][j], f[x][j-k] + f[t][k]);
}
}
}
}
int main()
{
while(cin >> n >> m)
{
init();
for (int i = 0; i < n; i++)
scanf("%d", &sor[i]);
for (int i = 1; i < n; i++)
{
int x, y;
scanf("%d%d", &x, &y);
son[x].push_back(y);
son[y].push_back(x);
}
dp(0);
int ans = 0;
for (int i = 0; i < n; i++)
ans = max(ans, f[i][m]);
printf("%d\n", ans);
}
return 0;
}
ps.个人理解树形dp就是以dfs为主体的一种dp,递归代替传统的递推。