【DP】选课 背包类树形dp

  • f[0][m]可知f[i][j]是以i为根节点的子树有的值,其中不包括i
  • 背包问题倒着循环--
  • 注意vector的使用 son[fa].push_back(i)即输入 son[x].size长度查询

遗留问题:

  1.  ·背包为什么倒着循环
  2. ·本题中f[x][t]=max(f[x][t],f[x][t-j]+f[y][j]);是否会重复计算
  3. ·tj循环能不能放在大括号外
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector> 
using namespace std;
vector<int>son[500];
int f[500][500],s[310],n,m;
void dp(int x) {
	f[x][0]=0;
	for(int i=0;i<son[x].size();i++) {
		int y=son[x][i];
		dp(y);
		for(int t=m;t>=0;t--)
		  for(int j=t;j>=0;j--)
		    f[x][t]=max(f[x][t],f[x][t-j]+f[y][j]);
	}
	if(x!=0) 
	  for(int t=m;t>0;t--)
	    f[x][t]=f[x][t-1]+s[x];
}
int main() {
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) {
		int fa;
		scanf("%d%d",&fa,&s[i]);
		son[fa].push_back(i); 
	}
	memset(f,0xcf,sizeof(f));
	dp(0);
	cout<<f[0][m]<<endl;
	return 0;
} 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值