P2014 [CTSC1997] 选课(树形DP但是没建树?)

树形DP就是在树状结构基础上的DP
树形DP的关键和实现方法是dfs(深度优先搜索),先找到树根,然后用dfs进行递归到叶子节点,自下而上的更新上层的 f 数组

小白不是很懂为什么树形DP没建树也能做?(这篇题解里面只是有一个树的概念)
树上背包:

#include<iostream>
#include<vector>
using namespace std;
vector<int>v[1314];
int m, n, f[1314][1314],c[1314];//第i门课程,修了j门课程,所得学分(背包问题)
void dfs(int u)
{
	for (int i = 0; i < v[u].size(); i++)//循环遍历每一个子节点
	{
		int x = v[u][i];
		dfs(x);
		for (int i = m; i >= 0; i--)//枚举总的分配的空间
		{
			for (int j = 0; j <= i; j++)//枚举子节点花费的空间
				f[u][i] = max(f[u][i], f[x][j] + f[u][i - j]);//子节点花费了j的空间,父节点就花费i-j的空间
		}
	}
	for (int i = m; i >= 1; i--)
		f[u][i] = f[u][i - 1] + c[u];//把当前u(父节点)加入
}
int main()
{
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
	{
		int a;
		cin >> a >> c[i];
		v[a]. push_back(i);//把子节点加入到父节点中
	}
	m++;//*****注意*****因为我们认为构造了一个0作为根节点,所以总的点数应该加一
	dfs(0);
	cout << f[0][m];

	return 0;
}

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

这道题的重点就是把原来的 森林通过加入一个0节点之后变为了一个以0为根节点的树

然后在这颗树上进行树上背包

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值