题目描述
在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习。现在有N门功课,每门课有个学分,每门课有一门或没有直接先修课(若课程a是课程b的先修课即只有学完了课程a,才能学习课程b)。一个学生要从这些课程里选择M门课程学习,问他能获得的最大学分是多少?
输入输出格式
输入格式:
第一行有两个整数N,M用空格隔开。(1<=N<=300,1<=M<=300)
接下来的N行,第I+1行包含两个整数ki和si, ki表示第I门课的直接先修课,si表示第I门课的学分。若ki=0表示没有直接先修课(1<=ki<=N, 1<=si<=20)。
输出格式:
只有一行,选M门课程的最大得分。
输入输出样例
输入样例#1:
7 4 2 2 0 1 0 4 2 1 7 1 7 6 2 2
输出样例#1:
13
0肯定是root
没有先修的课程一定和他相连
所以dfs从0开始
dp内容自己意会。。
树形dp
#include <cstdio> #include <vector> #define N 500 using namespace std; vector<pair<int,int> >G[N]; int n,m,f[N][N]; inline int max(int a,int b) {return a>b?a:b;} int dfs(int now,int pre) { int num=0; for(int i=0;i<G[now].size();++i) { int v=G[now][i].first,val=G[now][i].second; if(v==pre) continue; num+=dfs(v,now)+1; for(int j=num>m?m:num;j>=1;--j) for(int k=j-1;k>=0;--k) f[now][j]=max(f[now][j],f[now][j-k-1]+f[v][k]+val); } return num; } int Main() { scanf("%d%d",&n,&m); for(int x,y,i=1;i<=n;++i) { scanf("%d%d",&x,&y); G[x].push_back(make_pair(i,y)); } dfs(0,0); printf("%d\n",f[0][m]); return 0; } int sb=Main(); int main(int argc,char *argv[]) {;}
时间: 2024-10-08 15:08:00