hdu1561 樹形揹包初探

2021-07-02 03:43:00 字數 1016 閱讀 9571

problem description

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

input

每個測試例項首先包括2個整數,n,m.(1 <= m <= n <= 200);在接下來的n行裡,每行包括2個整數,a,b. 在第 i 行,a 代表要攻克第 i 個城堡必須先攻克第 a 個城堡,如果 a = 0 則代表可以直接攻克第 i 個城堡。b 代表第 i 個城堡的寶物數量, b >= 0。當n = 0, m = 0輸入結束。

output

對於每個測試例項,輸出乙個整數,代表acboy攻克m個城堡所獲得的最多寶物的數量。

思路dp(i,j,k)表示第i個子樹,用前j子節點,最多攻略k個城堡所獲得的最大利潤。除了dfs列舉第i個子樹外,在第i個子樹內的狀態轉移類似不作優化的多重揹包,所以也可以用滾動陣列的思想,省掉j這一維。dfs加上三重迴圈的轉移,遞推式詳見**。最後要注意迭代的順序~

#include #include #include #include using namespace std;

const int maxn = 205;

int w[maxn];

int dp[maxn][maxn];

int n,m;

int nexte[maxn];

int g[maxn];

void addedge()

}int dfs(int x){

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

dp[x][i] = w[x];

int num = 1;

for(int e=g[x];e!=-1;e=nexte[e]){

num += dfs(e);

dfs(e);

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

//k

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...

HDU 1561 樹形DP 揹包

題目鏈結 題目大意 從樹根開始取點。最多取m個點,問最大價值。解題思路 cost 1的樹形揹包。有個虛根0,取這個虛根也要cost,所以最後的結果是dp 0 m 1 本題是cost 1的特殊揹包問題,在兩個for迴圈上有乙個優化。for f 1.j.cost for 1.k.j cost 其中f為當...

HDU 1561(樹形dp 揹包問題)

題目 click 每個城堡被攻克,必須之前有乙個特定的城堡被攻克,才能攻占這個城堡。形成了一種子節點與父節點的關係,聯想到樹形dp取解決。走子節點必先走其父親節點,一次建樹,若無則父親節點為0 dp i j 表示以i為節點,取j個城堡寶藏獲得的最大值。include include include ...