• 树形dp--P2014 [CTSC1997]选课


    *传送

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

    确定状态:$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 }

  • 相关阅读:
    怎样才能算是在技术上活跃的小公司
    jquery幻灯片--渐变
    cpm效果介绍
    我依然热爱编程
    项目开发经验终结2015/4/7
    windows上putty访问ubuntu
    ubuntu安装openssh-server
    今天犯了一个低级错误
    linux 搭建lamp环境
    能用存储过程的DBHelper类
  • 原文地址:https://www.cnblogs.com/very-beginning/p/12460401.html
Copyright © 2020-2023  润新知