HDU 1561 The more, The Better(多重揹包+樹形DP)
阿新 • • 發佈:2019-02-20
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個城堡所獲得的最多寶物的數量。
Sample Input
3 2
0 1
0 2
0 3
7 4
2 2
0 1
0 4
2 1
7 1
7 6
2 2
0 0
Sample Output
5
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個城堡所獲得的最多寶物的數量。
Sample Input
3 2
0 1
0 2
0 3
7 4
2 2
0 1
0 4
2 1
7 1
7 6
2 2
0 0
Sample Output
5
13
思路:dp[i][j]表示對於第i個結點以及他的所有子節點,取j個時的最大價值。
對於每個結點,就相當於求取他的子節點若干個獲得的最大價值,即一個多重揹包問題。但由於每個子節點取的個數不同,價值並不是倍數關係的,所以不能用二進位制優化,只能直接列舉。
#include <iostream> #include <stdio.h> #include <cmath> #include <algorithm> #include <iomanip> #include <cstdlib> #include <string.h> #include <vector> #include <queue> #include <stack> #include <ctype.h> using namespace std; int n,m; vector<int> G[1005]; //記錄i結點的子節點 int v[1005]; //記錄i結點的價值 int fa[1005]; //記錄i結點的父親 int cnt[1005]; //記錄i結點以及他的子孫節點的總個數 int dp[1005][1005]; void dfs(int s) { for(int i=0;i<=n;i++) { dp[s][i]=v[s]; } cnt[s]=1; for(int i=0;i<G[s].size();i++) //列舉子節點 { dfs(G[s][i]); cnt[s]+=cnt[G[s][i]]; for(int j=cnt[s];j>1;j--) //列舉一共取j個 { for(int k=1;k<=cnt[G[s][i]]&&k<=j-1;k++) //列舉第i個子節點取k個 { dp[s][j]=max(dp[s][j],dp[G[s][i]][k]+dp[s][j-k]); } } } } int main() { while(scanf("%d%d",&n,&m)!=EOF) { if(n==0 && m==0) break; memset(dp,0,sizeof(dp)); memset(cnt,0,sizeof(cnt)); for(int i=0;i<=n;i++) G[i].clear(); for(int i=1;i<=n;i++) { scanf("%d%d",&fa[i],&v[i]); G[fa[i]].push_back(i); } dfs(0); cout<<dp[0][m+1]<<endl; //這裡相當於第0個結點也取了一個,所以m+1 } return 0; }