HDU-1561-樹形dp+背包
阿新 • • 發佈:2018-04-18
NPU gree 樹形dp sample sin dfs scrip ria code
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輸入結束。
Sample Output
5
13
The more, The Better
Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 9169 Accepted Submission(s): 5343
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
Author 8600 註意到寶物之間的關系可以用一顆有向樹來表示,0號節點就是根,用f[i][j]表示由i號節點延伸j個節點(包括i在內)可以達到的最大價值,對於當前節點,對他的每一個兒子跑一遍背包,枚舉當前兒子包含的節點數k,那麽之前所有兒子包含的節點數就是j-k(算上父親),最後答案就是f[0][m+1]; 註意節點數j要降序枚舉否則更新後的數組會影響後面的狀態。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define inf 0x3f3f3f3f 4int first[220],tot; 5 int f[210][210]; 6 struct Edge 7 { 8 int v,next; 9 }e[500]; 10 void add(int u,int v) 11 { 12 e[tot].v=v; 13 e[tot].next=first[u]; 14 first[u]=tot++; 15 } 16 int b[220],M,N; 17 int dfs(int u) 18 { 19 f[u][1]=b[u]; 20 int s=1; 21 for(int i=first[u];~i;i=e[i].next){ 22 int v=e[i].v; 23 int son=dfs(v); 24 s+=son; 25 for(int j=M+1;j>=1;--j){ 26 for(int k=1;j-1>=k&&k<=son;++k){ 27 f[u][j]=max(f[u][j],f[u][j-k]+f[v][k]); 28 } 29 } 30 } 31 return s; 32 } 33 int main() 34 { 35 int n,m,i,j,k; 36 while(cin>>n>>m&&(n||m)){ 37 N=n,M=m; 38 memset(f,0,sizeof(f)); 39 memset(first,-1,sizeof(first)); 40 tot=0; 41 for(i=1;i<=n;++i){ 42 scanf("%d%d",&k,&b[i]); 43 add(k,i); 44 } 45 dfs(0); 46 //cout<<f[1][1]<<‘ ‘<<f[2][1]<<‘ ‘<<f[3][1]<<endl; 47 cout<<f[0][m+1]<<endl; 48 } 49 return 0; 50 }
HDU-1561-樹形dp+背包