• 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 }
  • 相关阅读:
    LeetCode 461. Hamming Distance
    LeetCode 442. Find All Duplicates in an Array
    LeetCode 448. Find All Numbers Disappeared in an Array
    LeetCode Find the Difference
    LeetCode 415. Add Strings
    LeetCode 445. Add Two Numbers II
    LeetCode 438. Find All Anagrams in a String
    LeetCode 463. Island Perimeter
    LeetCode 362. Design Hit Counter
    LeetCode 359. Logger Rate Limiter
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4236187.html
Copyright © 2020-2023  润新知