AW286 选课(背包类树形DP)

AW286 选课(背包类树形DP)

题目地址


易错点:

  • 分组背包需要反向循环以保证状态转移的正确性.
  • f[x][0]在dp前就初始化了,因此可以不枚举体积为0的情况.
  • 注意初始化.

#include<cstdio>
#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
const int MAXN=500;
int f[MAXN][MAXN],score[MAXN];
vector<int> son[MAXN];
int m;
void dp(int x){
	f[x][0]=0;
	if(!son[x].empty()){
		int size=son[x].size();
		for(int i=0;i<size;i++){
			int y=son[x].at(i);
			dp(y);
			for(int j=m;j>=1;j--){
				for(int k=1;k<=j;k++){
					f[x][j]=max(f[x][j],f[x][j-k]+f[y][k]);
				}
			}
		}
	}
	if(x!=0){
		for(int i=m;i>=1;i--){
			f[x][i]=f[x][i-1]+score[x];
		}
	}
}
int main(){
	memset(f,0xcf,sizeof(f));
	int n;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		int fa,nowScore;
		scanf("%d%d",&fa,&nowScore);
		son[fa].push_back(i);
		score[i]=nowScore;
	}
	dp(0);
	printf("%d
",f[0][m]);
	return 0;
}