C++ P2014 选课
题目描述在大学里每个学生,为了达到一定的学分,必须从很多课程里选择一些课程来学习,在课程里有些课程必须在某些课程之前学习,如高等数学总是在其它课程之前学习。现在有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 题目地址:https://www.luogu.org/problemnew/show/P2014 个人思路: 本质上仍然是背包问题,但是这里把背包问题转化到了树上 所以,在dfs的同时进行背包dp(分组背包)即可 #include #include using namespace std; int score[1010],ans,n,m,f[1010][1010],head[1010],cnt; struct edge{ int from,to,nxt; }e[1010]; void add(int from,int to){ e[++cnt].from=from; e[cnt].to=to; e[cnt].nxt=head[from]; head[from]=cnt; } void dp(int x){ for(int i=head[x];i;i=e[i].nxt){ int v=e[i].to; dp(v); for(int t=m;t;t--)//循环当前选课总门数(背包体积) for(int j=t;j;j--){//循环更深子树上的选课门数(组内物品) if(t-j>=0) f[x][t]=max(f[x][t],f[x][t-j]+f[v][j]); ans=max(ans,f[x][t]); } } if(x!=0) for(int t=m;t;t--){ f[x][t]=f[x][t-1]+score[x]; ans=max(ans,f[x][t]); } } int main(){ ans=-2000000000; cin>>n>>m; int fa; for(int i=1;i<=n;i++){ cin>>fa>>score[i]; add(fa,i); } dp(0); printf("%dn",ans); return 0; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |