Luogu P2014 选课___背包+树形dp
2018-03-20 21:11
260 查看
题目大意:
现在有N门功课,每门课有个学分,每门课有一门或没有直接先修课(若课程a是课程b的先修课即只有学完了课程a,才能学习课程b)。给出每一门课的先修课ki和学分si,一个学生要从这些课程里选择M门课程学习,问他能获得的最大学分是多少?ki=0时表示没有先修课
1<=ki<=N, 1<=si<=20
1<=N<=300,1<=M<=300
题解:
一个树形dp跟背包的结合设f[i][j]表示以i为根的子树中选j门课能够获得的最高学分
然后枚举它所有的儿子,
设k为i的一个儿子,它用了l的体积,
l保证严格≤j-1 //此时i≠0
那么f[i,j]=min(f[i][j],f[k][l]+f[i][j-l])
最后将f[i,j]加上对应的学分,j≥1
代码:
#include<bits/stdc++.h> #define N 305 using namespace std; int n,m,x,f ,listr ,next ,a ; void tree_dp(int dep) { f[dep][0]=0; int k=listr[dep]; while (k) { tree_dp(k); for (int i=n; i>=0; i--) for (int j=i; j>=0; j--) f[dep][i]=max(f[dep][i],f[dep][i-j]+f[k][j]); k=next[k]; } if (dep!=0) { for (int i=n; i>0; i--) f[dep][i]=f[dep][i-1]+a[dep]; } } int main() { scanf("%d%d",&m,&n); for (int i=1; i<=m; i++) { scanf("%d%d",&x,&a[i]); next[i]=listr[x]; listr[x]=i; } tree_dp(0); printf("%d\n",f[0] ); return 0; }
相关文章推荐
- 洛谷 p2014 [CTSC2001] 选课 树形背包DP
- 树形DP+(分组背包||二叉树,一般树,森林之间的转换)codevs 1378 选课
- 树形dp-洛谷 P2014 选课
- 【Luogu P2014 选课】【树形背包学习笔记】
- 洛谷 2014 选课 树形DP 解题报告
- joyOI 选课 【树形dp + 背包dp】
- Regionals 2014 >> Asia - Taichung 7003 - A Balance Game on Trees 树形DP + 二维费用背包
- 树形DP——Luogu2014 选课
- [Luogu2014]选课 树形DP
- luogu P2014 选课 树形背包
- Codevs1378选课[树形DP|两种做法(多叉转二叉|树形DP+分组背包)---(▼皿▼#)----^___^]
- P2014 选课(树形背包)
- BZOJ.4753.[JSOI2016]最佳团体(01分数规划 树形背包DP)
- bzoj3829 [Poi2014]FarmCraft(树形dp+贪心)
- poj 2486 Apple Tree (树形背包dp)
- bzoj 3566: [SHOI2014]概率充电器 概率dp+树形dp
- bzoj 3611: [Heoi2014]大工程 虚树+树形dp
- bzoj 3572: [Hnoi2014]世界树 (虚树+树形DP+LCA)
- hdu5148 树形dp,分组背包
- 【BZOJ-1017】魔兽地图DotR 树形DP + 背包