题目描述
在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习。现在有 NN 门功课,每门课有个学分,每门课有一门或没有直接先修课(若课程a是课程b的先修课即只有学完了课程a,才能学习课程b)。一个学生要从这些课程里选择 MM 门课程学习,问他能获得的最大学分是多少?
dp[i][j] 表示在以i为根的子树选j门课(包括i)能够获得的最高学分
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <vector>
#define ll long long
using namespace std;
int n,m,dp[305][305],x;
vector<int> a[305];
void dfs(int x)
{
for(int i=0;i<a[x].size();i++)
{
int y=a[x][i];
dfs(y);
for(int j=m+1;j>=1;j--)//01分组背包 体积
{
for(int k=0;k<j;k++)//决策
{
dp[x][j]=max(dp[x][j],dp[y][k]+dp[x][j-k]);
}
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n >> m;
for(int i=1;i<=n;i++)//森林,0号节点充当根节点
{
cin >> x >> dp[i][1];
a[x].push_back(i);
}
dfs(0);
cout << dp[0][m+1] << endl;
return 0;
}