hdu1011(树形背包)
http://acm.hdu.edu.cn/showproblem.php?pid=1011
题意:
是有n个洞组成一棵树,你有m个士兵,你从1号房间开始攻打,每个洞有a个"bugs"和b的价值。你的一个士兵可以打20个"bugs",为了拿到这个洞的价值b你必须留下k个士兵消灭这个洞的所有"bugs"(k*20>="bugs"的数量,且留下的士兵不可以再去攻打其他的洞,且必须攻打了前面的洞才可以攻打后面的洞)。问你花费这m个士兵可以得到的最大价值是多少。
dp方程:
dp[p][j]=max(dp[p][j],dp[p][j-k]+dp[ son[p] ][ k ])
1 #include <iostream> 2 #include <vector> 3 #include <cstring> 4 #include <cstdio> 5 using namespace std; 6 const int Ni = 110; 7 int n,m; 8 int cos[Ni],weg[Ni]; 9 int dp[Ni][Ni]; 10 bool vis[Ni]; 11 vector<int> dv[Ni]; 12 inline int max(int a,int b){return a>b? a:b;} 13 void dfs(int p) 14 { 15 int i,j,k; 16 int temp=(cos[p]+19)/20; 17 for(i=temp;i<=m;i++) dp[p][i]=weg[p]; 18 vis[p]=1; 19 for(i=0;i<dv[p].size();i++) 20 { 21 int t=dv[p][i]; 22 if(vis[t]) continue; 23 dfs(t); 24 for(j=m;j>=temp;j--) 25 { 26 for(k=1; k<=j-temp; k++)//留下temp攻打p 27 dp[p][j]=max(dp[p][j],dp[p][j-k]+dp[t][k]); 28 } 29 } 30 } 31 int main() 32 { 33 int i; 34 while(scanf("%d%d",&n,&m),n!=-1||m!=-1) 35 { 36 for(i=0; i<=n; i++) dv[i].clear(); 37 memset(dp,0,sizeof(dp)); 38 memset(vis,0,sizeof(vis)); 39 for(i=1; i<=n; i++) 40 scanf("%d%d",cos+i,weg+i); 41 for(i=1; i<n; i++) 42 { 43 int u,v; 44 scanf("%d%d",&u,&v); 45 dv[u].push_back(v); 46 dv[v].push_back(u); 47 } 48 if(m==0) {printf("0\n");continue;} 49 dfs(1); 50 printf("%d\n",dp[1][m]); 51 } 52 return 0; 53 }
5 2
0 1 0 1 0 5 0 1 0 2 1 2 1 3 2 4 2 5
ans: 9