程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> hdu 1561 The more, The Better (樹形背包dp)

hdu 1561 The more, The Better (樹形背包dp)

編輯:C++入門知識

題目鏈接:   hdu-1561


題目
ACboy很喜歡玩一種戰略游戲,在一個地圖上,有N座城堡,每座城堡都有一定的寶物,在每次游戲中ACboy允許攻克M個城堡並獲得裡面的寶物。但由於地理位置原因,有些城堡不能直接攻克,要攻克這些城堡必須先攻克其他某一個特定的城堡。你能幫ACboy算出要獲得盡量多的寶物應該攻克哪M個城堡嗎?

 

 

思路
簡單樹形背包dp,當作樹形背包的第一道入門題非常合適

題目給的是森林,那麼給增加一個"根節點", 指向森林中的每個樹的根節點
f(i, j)表示子樹i, 取j個城堡寶藏的時候的最大值
i的每個子節點表示的子樹可以看作是一組物品,在這個子樹上可以選擇取1,2,3...j-1個的城堡寶藏
那麼就是等價於對每個子節點做分組背包.


f(i, j) = max{ max{f(i, j-k)+f(v, k) | 1<=k<j }  |  v是i的子樹  }

因為增加了一個根節點,而且拿子節點之前必須先拿父節點,所以m值要增加1,用來拿根節點.

有個優化, 對於某個子樹,它取的個數不可能超過這個子樹的節點數,優化了可以到0MS

 

 

代碼

  /**===================================================== *  
 This is a solution for ACM/ICPC problem * *   @source     
 : hdu-1561 The more, The Better * 
  @description : 樹形背包dp * 
  @author      : shuangde *   @blog      
  : blog.csdn.net/shuangde800 *   @email   
    : [email protected] *  
 Copyright (C) 2013/08/20 11:27 All rights reserved. 
 *======================================================*/
#include <iostream>#include
 <cstdio>#include 
<algorithm>#include <vector>
#include <queue>
#include <cmath>
#include <cstring>
#define MP make_pairusing namespace std;
typedef pair<int, int >PII;
typedef long long int64;
const int INF = 0x3f3f3f3f;
const double PI  = acos(-1.0);
const int MAXN = 210;vector<int>adj[MAXN];
int val[MAXN];
int tot[MAXN];
int f[MAXN][MAXN];
int n, m;
int dfs(int u) {    f[u][1] = val[u];
    tot[u] = 1;  
  for (int i = 0; i < adj[u].size(); 
++i) {        int v = adj[u][i];   
     tot[u] += dfs(v);   
 }    for (int i = 0; i < adj[u].size(); 
++i) {        int v = adj[u][i];       
 for (int s = tot[u]>m?m:tot[u]; s >= 1; 
--s) {            for (int j = 1;
 j < s && j <= tot[v]; 
++j) {                f[u][s] = max(f[u][s], f[u][s-j] + f[v][j]);   
          }        }    }    return tot[u];
}int main(){    while (~scanf("%d %d", &n, &m) && n + m) {        // init        for (int i = 0;
 i <= n; ++i)            adj[i].clear();   
     val[0] = 0;   
     for (int i = 1; i <= n; ++i) {            int a; 
           scanf("%d %d", &a, &val[i]);     
       if (a) {                adj[a].push_back(i);    
         } else {                adj[0].push_back(i);   
          }        }        memset(f, 0, sizeof(f));   
     ++m;        dfs(0);    
    printf("%d\n", f[0][m]);  
  }    return 0;} 

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved