HDU 1011 Starship Troopers星河战队(树形dp)
生活随笔
收集整理的這篇文章主要介紹了
HDU 1011 Starship Troopers星河战队(树形dp)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
?
?
題意
有n個洞穴編號為1~n,洞穴間有通道,形成了一個n-1條邊的樹, 洞穴的入口即根節(jié)點是1。
每個洞穴有x只bugs,并有價值y的金子,全部消滅完一個洞穴的蟲子,就可以獲得這個洞穴的y個金子.
現(xiàn)在要派m個戰(zhàn)士去找金子,從入口進入。每次只有消滅完當(dāng)前洞穴的所有蟲子,才可以選擇進入下一個洞穴。
一個戰(zhàn)士可以消滅20只蟲子,如果要殺死x只蟲子,那么要x/20向上取整即(x+19)/20個戰(zhàn)士。
如果要獲得某個洞穴的金子,必須留下足夠殺死所有蟲子的戰(zhàn)士數(shù)量, 即(x+19)/20個戰(zhàn)士,然后這些留下戰(zhàn)士就不能再去其它洞穴
其他戰(zhàn)士可以繼續(xù)走去其它洞穴,可以選擇分組去不同的洞穴。
戰(zhàn)士只能往洞穴深處走,不能走回頭路。
問最多能獲得多少金子?
?
?
?
?思路:
基礎(chǔ)的樹形DP。
要特別注意的是,如果某個節(jié)點的bug數(shù)為0,而金子不為0,那么仍然需要派1個人以上去撿,而不是花0個士兵就能獲得該點的金子。
?
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N=110; 4 vector<int> vect[N]; 5 int bug[N], num[N], dp[N][N], n, m; 6 7 void DFS(int t,int far,int peo) 8 { 9 int need=(bug[t]+19)/20; 10 if(peo<need || peo==0) return ; 11 12 for(int i=need; i<=peo; i++) dp[t][i]=num[t]; //若有士兵i>=need個,那么起碼拿到本節(jié)點的金子 13 for(int i=0; i<vect[t].size(); i++) 14 { 15 int to=vect[t][i]; 16 if(to^far) 17 { 18 DFS(to, t, peo-need); 19 for(int j=peo; j>need; j--) //到達本節(jié)點可能的人數(shù)。 20 for(int k=1; k<=j-need; k++) //給孩子to分配k個士兵。 21 dp[t][j]=max(dp[t][j],dp[t][j-k]+dp[to][k]); 22 } 23 } 24 } 25 26 27 int main() 28 { 29 freopen("input.txt","r",stdin); 30 int u,v; 31 while(scanf("%d%d",&n,&m), n+m>0) 32 { 33 for(int i=0; i<=n; i++) vect[i].clear(); 34 memset(dp,0,sizeof(dp)); 35 36 for(int i=1; i<=n; i++) //房間里的bug數(shù)、金子 37 scanf("%d%d",&bug[i],&num[i]); 38 for(int i=1; i<n; i++) //連通情況 39 { 40 scanf("%d%d",&u,&v); 41 vect[u].push_back(v); 42 vect[v].push_back(u); 43 } 44 DFS(1, -1, m); 45 printf("%d\n", dp[1][m]); 46 } 47 return 0; 48 } AC代碼?
轉(zhuǎn)載于:https://www.cnblogs.com/xcw0754/p/4241459.html
總結(jié)
以上是生活随笔為你收集整理的HDU 1011 Starship Troopers星河战队(树形dp)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 迅捷CAD编辑器中比较好用的功能
- 下一篇: 【Windows】清理'设备和驱动器'的