題意:n座城堡,每個裡面都有寶物,要求在你可以攻占m個城堡得到的最多的寶物,但是如果要攻破乙個城堡,必須要攻破它依賴的那個城堡,例如,如果a依賴b,那麼如果想要攻破a就必須先攻破b。把每個城堡看作是物品,那麼這個物品的城堡數量是1,價值就是寶物了。
解題思路:根據題意知道這種關係會形成一顆多叉樹,根節點是0.從p=0開始,
1、遍歷所有p的孩子,遇到某個孩子還有孩子,就把該節點當作p,繼續1,直到遍歷完所有的節點,如果p的所有孩子都沒有孩子,那麼轉到2,存在有的孩子有孩子,轉到3;
2、對p的所有孩子進行01揹包,假設p的價值是vp,p共有n個孩子,然後對每個孩子進行01揹包(因為對於每個城堡只能取一次),那麼可以得到城堡數量從0到n對應的最大價值(0對應的肯定是0了),用dp[i]表示,i代表城堡數量,dp[i]代表價值,接著從i=0開始,都加上p的價值vp(因為所有的物品都依賴p),同時城堡的個數也加1;最後把得到的n+1個物品儲存到p點,這樣,這些物品就相當於分組揹包裡面的一組揹包了,儲存在castle裡面,然後接著步驟1的遍歷;
3、這個就很簡單了,由於已經遍歷過p所有孩子了,所以,只需要再從頭開始遍歷一遍所有孩子,如果遍歷的孩子還有孩子,那麼就把它的所有孩子當作是分組揹包處理,如果遍歷的孩子沒有孩子,那麼就當01揹包處理,最後會得到乙個城堡數量從0到m(也就是題目給的城堡數量的上限,以為不確定p的所有孩子的個數,所以就用最大的m)對應的最大價值,這個時候,如果p是0,那麼就輸出dp[m]就好了,如果不是,像2一樣,dp[i]代表的價值都加上p的價值,數量也加1,也儲存在castle裡面,繼續步驟1的遍歷;
具體**如下:
(提示:結構體s[i]代表城堡i的資訊:num表示城堡的數量,value代表價值,key是自身的序號,depend代表i依賴的城堡編號;list castle[i]記錄依賴i的城堡的資訊)
[cpp]
#include
#include
#include
#include
using namespace std;
#define n 205
struct sss[n],one;
list castle[n];
int dp[n],m;
void fun(int n)
memset(dp,0,sizeof(dp));
p=castle[n].begin();
while(p!=castle[n].end())
} }
else
p++;
} castle[n].clear();
if(!n)
cout<
else
else
} }
} int main()
fun(0);
} } 作者:jiang199235jiangjj
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...
hdu1561 樹上分組揹包
hdu1561 樹上揹包模板題 題意大概是給一棵樹,每個點有相應的權值,從樹根開始選取m個連通的點然後使得獲得的點權最大。我們假設dp u j 為以u點為根時,向下選取j個點獲得的最大權值。v為u的子節點,那麼可以看出其實當u點可以最多向下取p個點的時候,u點可以視為乙個容量為p的揹包,物品為dp ...