hdu 1561 樹形dp,hdu1561樹形dp
http://acm.hdu.edu.cn/showproblem.php?pid=1561
Problem DescriptionACboy很喜歡玩一種戰略遊戲,在一個地圖上,有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個城堡所獲得的最多寶物的數量。
Sample Input
3 20 10 20 37 42 20 10 42 17 17 62 20 0
Sample Output
513
Author8600
/**hdu 1561 樹形dp題目大意:中文題不在贅述解題思路:加一個根節點0,構成一棵樹。背包,dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]);( j:2~m; k:1~j-1 )*/#include <stdio.h>#include <string.h>#include <algorithm>#include <iostream>using namespace std;const int maxn=205;struct note{ int v,next;}edge[maxn*2];int head[maxn],ip;int n,m,dp[205][205],a[205];void init(){ memset(head,-1,sizeof(head)); ip=0;}void addedge(int u,int v){ edge[ip].v=v,edge[ip].next=head[u],head[u]=ip++;}void dfs(int u,int pre){ for(int i=1;i<=m;i++) dp[u][i]=a[u]; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(v==pre)continue; dfs(v,u); for(int j=m;j>1;j--) { for(int k=1;k<j;k++) dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]); } }}int main(){ while(~scanf("%d%d",&n,&m)) { if(n==0&&m==0)break; m++; init(); a[0]=0; for(int i=1;i<=n ;i++) { int v,w; scanf("%d%d",&v,&w); addedge(i,v); addedge(v,i); a[i]=w; } memset(dp,0,sizeof(dp)); dfs(0,-1); printf("%d\n",dp[0][m]); } return 0;}/***3 20 10 20 37 72 20 10 42 17 17 62 20 0*/
Problem DescriptionACboy很喜歡玩一種戰略遊戲,在一個地圖上,有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個城堡所獲得的最多寶物的數量。
Sample Input
3 20 10 20 37 42 20 10 42 17 17 62 20 0
Sample Output
513
Author8600