hdu1561 樹上分組揹包

2021-07-26 04:37:44 字數 1627 閱讀 4560

hdu1561 樹上揹包模板題 題意大概是給一棵樹,每個點有相應的權值,從樹根開始選取m個連通的點然後使得獲得的點權最大。

我們假設dp[u][j]為以u點為根時,向下選取j個點獲得的最大權值。 v為u的子節點,那麼可以看出其實當u點可以最多向下取p個點的時候,u點可以視為乙個容量為p的揹包,物品為dp[v][k] 物品的代價為k ,價值為dp[v][k],那麼就可以當做分組揹包來做(即可以從每個子節點v以及v的子孫中選取xi個點,且∑xi = p - 1),但是【這裡有個地方要注意,由於要求的是選取連通的點,即當我們選了v點的子節點時,v點也應該一併選取。同理u點本身也必須被選取】,我們可以把dp[u][1] 初始化為 val[u],即該點本身的權值,同時我們稍微改動一下方程的列舉過程即可 

for(int j = m ;j > 1; -- j)

for(int k = 1 ; k <= m-1 ;++ k)

if(j > k)

dp[u][j] = max(dp[u][j], dp[u][ j - k] + dp[v][ k ]);

dp[u][1]這個狀態不去更新,可以使得dp[u][j] (2 <= j <= p)時 都是從dp[u][1]進行轉移的 , 即保證一定是取了其本身這個點的權值。

我們可以從葉子往上進行dp,也可以從根往下進行dfs。

根據這個題同時也可以解決樹上最大的連通點問題。

#include#include#include#include#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;

#define long long long

const long inf=0x3f3f3f3f;

const long mod=10000;

const double pi=acos(-1.0);

#define clri(x) memset(x,-1,sizeof(x))

#define clr0(x) memset(x,0,sizeof x)

#define clr1(x) memset(x,inf,sizeof x)

#define clr2(x) memset(x,-inf,sizeof x)

#define eps 1e-10

struct edgeedge [1000];

int dp[300][300] ;

int head[300];

int val[300];

int tot ;

void add_edge (int u , int v )

void init()

void dfs( int u , int m)

}int main()

dp[0][1] = 0;

m++ ;

dfs( 0 , m);

// for(int i = 0; i<= n ;++ i)

// {

// for(int j = 1 ;j <= 5 ;++ j)

// printf("%d ",dp[i][j]);cout<

hdu 1561 依賴揹包

題意 n座城堡,每個裡面都有寶物,要求在你可以攻占m個城堡得到的最多的寶物,但是如果要攻破乙個城堡,必須要攻破它依賴的那個城堡,例如,如果a依賴b,那麼如果想要攻破a就必須先攻破b。把每個城堡看作是物品,那麼這個物品的城堡數量是1,價值就是寶物了。解題思路 根據題意知道這種關係會形成一顆多叉樹,根節...

hdu1561 樹形揹包初探

problem description acboy很喜歡玩一種戰略遊戲,在乙個地圖上,有n座城堡,每座城堡都有一定的寶物,在每次遊戲中acboy允許攻克m個城堡並獲得裡面的寶物。但由於地理位置原因,有些城堡不能直接攻克,要攻克這些城堡必須先攻克其他某乙個特定的城堡。你能幫acboy算出要獲得盡量多的...

HDU 1561 樹形dp 揹包

分析 攻下一座城堡的前提是要先攻下它的前驅城堡,建立乙個以0為根結點的樹,他的權值為0 dp i,j 表示以i為根結點去j個的最大值。dp i,1 v i v i 為攻下i城堡獲得的寶藏 對與u結點取j 1個,可以轉化為以孩子i為根取k個 以自己為根取j 1 k個和自己取j 1個的最大值 為什麼是j...