首页 > 其他 > 详细

树形dp--P2014 [CTSC1997]选课

时间:2020-03-11 10:08:48      阅读:58      评论:0      收藏:0      [点我收藏+]

*传送

思路:因为有的学科有直接先修课(选了先修课才能选当前课程),所以我们可以让当前课程指向他的先修课,这样只要先修课没有选,他的子树就没有办法选。

确定状态:f[i][j]表示选择i节点选j门课程的最大价值

转移方程:f[u][j]=max(f[u][j],f[to][k]+f[u][j-k])

       其中u表示的是当前节点,to表示他的子节点

     方程式的意义为:f[u][j]表示选或不选当前节点,但不选子树,一共选了j个课程的最大价值

             f[to][k]+f[u][j-k]表示选择当前节点,并选择他的k个子节点,一共选了j个节点的最大价值 

*注:初始化的时候f[i][1]表示只选择当前节点,他的值就是这门课的学分

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstdio>
 4 #include <cmath>
 5 using namespace std;
 6 int n,m;
 7 struct node{
 8     int next,to;
 9 }ed[305];
10 int head[305],tot,f[305][305],fa;
11 void add(int u,int v){
12     ed[++tot].next=head[u];
13     ed[tot].to=v;
14     head[u]=tot;
15 }
16 void dp(int u){
17     for (int i = head[u];i;i=ed[i].next){
18         int to=ed[i].to;
19         dp(to);
20         for (int j = m+1;j >= 1;j--){
21             for (int k = 0;k < j;k++){
22                 f[u][j]=max(f[u][j],f[to][k]+f[u][j-k]);    
23             }
24         }
25     }
26 }
27 int main(){
28     scanf ("%d%d",&n,&m);
29     for (int i = 1;i <= n;i++){
30         scanf ("%d%d",&fa,&f[i][1]);
31         add(fa,i);
32     }
33     dp(0);
34     cout<<f[0][m+1];
35     return 0;
36 }

 

技术分享图片

 

树形dp--P2014 [CTSC1997]选课

原文:https://www.cnblogs.com/very-beginning/p/12460401.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!