• POJ 2486 树形dp


    题目大意:

    从 1 号点出发,每次经过一个点,就可以得到点上的所有苹果,走m步,求能够得到的苹果最大数量

    这里用dp[u][j] 表示 从u号点出发走 j 步后回到u点能得到的苹果最大数量

    用ans[u][j] 表示从 u 号点出发走 j 步不一定回到u点能得到的苹果最大数量(包括了dp[u][j]的情况)

    因为从父亲到儿子,最后又要回到父亲需要多走2次

    dp[u][j+2] = max{dp[v][k] + dp[u][j-k]} k<=j , j<=m

    对于ans[][]来说因为不确定它是否回到父亲,所以根据dp[][]来算

    要从一棵子树到另一棵子树,那么必然经过父亲 , 那么这两棵子树中可能是原子树回到了原点 , 那么当前子树就没必要回到原点,那么当前边只要去不用回来

    ans[u][j+1] = max{ans[v][k] + dp[u][j-k]}

    又可能是当前子树回到了原点 , 那么原子树就没必要回到原点,那么就是从父亲先去当前子树,再回来经过原来的子树合并,当前边来回就是多走两次

    ans[u][j+2] = max{dp[v][k] + ans[u][j-k]}

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 using namespace std;
     5 const int N = 205;
     6 int val[N] , first[N] , k , dp[N][N] , ans[N][N];
     7 
     8 struct Edge{
     9     int y , next;
    10 }e[N<<1];
    11 
    12 void add_edge(int x, int y)
    13 {
    14     e[k].y = y , e[k].next = first[x];
    15     first[x] = k++;
    16 }
    17 
    18 void dfs(int u , int fa , int m)
    19 {
    20     ans[u][0] = dp[u][0] = val[u];
    21     for(int i = first[u] ; i!=-1 ; i=e[i].next){
    22         int v = e[i].y;
    23         if(v == fa) continue;
    24         dfs(v , u , m);
    25         for(int j=m ; j>=0 ; j--){
    26             for(int k=j ; k>=0 ; k--){
    27                 dp[u][j+2] = max(dp[u][j+2] , dp[v][k] + dp[u][j-k]);
    28                 ans[u][j+2] = max(dp[v][k] + ans[u][j-k] , ans[u][j+2]);
    29                 ans[u][j+1] = max(ans[v][k] + dp[u][j-k] , ans[u][j+1]);
    30             }
    31         }
    32     }
    33 }
    34 
    35 int main()
    36 {
    37   // freopen("a.in" , "r" , stdin);
    38     int n,m,x,y;
    39     while(scanf("%d%d" , &n , &m)==2)
    40     {
    41         for(int i=1 ; i<=n ; i++)
    42             scanf("%d" , val+i);
    43         memset(first , -1 , sizeof(first));
    44         k = 0;
    45         for(int i=1 ; i<n ; i++){
    46             scanf("%d%d" , &x , &y);
    47             add_edge(x , y);
    48             add_edge(y , x);
    49         }
    50         memset(ans , 0 , sizeof(ans));
    51         memset(dp , 0 , sizeof(dp));
    52 
    53         dfs(1 , -1 , m);
    54 
    55         int maxn = 0;
    56         for(int i=0 ; i<=m ; i++)
    57             maxn = max(maxn , ans[1][i]);
    58         printf("%d
    " , maxn);
    59     }
    60     return 0;
    61 }
  • 相关阅读:
    趣题:寻找出现了奇数次的数
    zstu2016校赛圣杯战争
    HDU 5183 Negative and Positive (NP) ——(后缀和+手写hash表)
    HDU 5673 Robot ——(卡特兰数)
    HDU 3775 Chain Code ——(Pick定理)
    2016 ICPC北京站现场赛总结(再度流水账)
    2014苏州大学新生赛第二场(12.10)题目解析
    【Jump Game II 】cpp
    【Jump Game】cpp
    【 Sqrt(x) 】cpp
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4236187.html
Copyright © 2020-2023  润新知