链接
题意
这里有\(n\)个课程,你需要从它们中选出一些来学习,然而有些课程必须在某些课程之前学习,如高等数学总是在其他课程之前学习。每门课程有个学分,对于一门课必须先修它的先修课才能再修它,你需要从这些课程里选择m门课程学习,问它能获得的最大学分。
输入格式:第一行两个整数\(n,m\)用空格隔开,接下来\(n\)行,第\(i+1\)包含两个整数\(k\)和\(s\),\(k\)表示第\(i\)门课的直接先修课,\(s\)表示第\(i\)门课的学分,\(k=0\)表示没有直接先修课。
数据范围:\(1\leq n\leq 300,1\leq m\leq 300,1\leq k\leq n,1\leq s\leq 20\).
输出格式:输出一行,选\(m\)门课的最大得分。
分析
这是一个树形背包的经典入门题。
没门课的先修课最多只有一个,所以课与课之前的先修关系构成了一棵树。我们构造一个虚拟节点0,对于那些没有先修课的课程,规定先修课为0,并且选0的学分为0,那么问题就转化成了,从这个以0为根节点的树中,选\(m+1\)门课。
设\(dp[x][t]\)表示在以\(x\)为根的子树中选取\(t\)门课,能获得的最大学分,对于\(x\)的每个子节点\(y_i\),我们可以在以\(y_i\)为根的子树中选修若干门课\(c_i\),在满足\(\sum c_i=t-1\)的基础上获得尽量多的学分。
这即是一个分组背包,物品组数为\(x\)子节点\(y_i\)的个数,每组物品共\(t-1\)个,背包体积为\(t-1\),第\(i\)组第\(j\)个物品体积为\(j\)。
代码
1 |
|