日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

HDU 1011 Starship Troopers星河战队(树形dp)

發布時間:2024/5/14 编程问答 62 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HDU 1011 Starship Troopers星河战队(树形dp) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?

?

題意

  有n個洞穴編號為1~n,洞穴間有通道,形成了一個n-1條邊的樹, 洞穴的入口即根節點是1。
  每個洞穴有x只bugs,并有價值y的金子,全部消滅完一個洞穴的蟲子,就可以獲得這個洞穴的y個金子.
  現在要派m個戰士去找金子,從入口進入。每次只有消滅完當前洞穴的所有蟲子,才可以選擇進入下一個洞穴。
  一個戰士可以消滅20只蟲子,如果要殺死x只蟲子,那么要x/20向上取整即(x+19)/20個戰士。
  如果要獲得某個洞穴的金子,必須留下足夠殺死所有蟲子的戰士數量, 即(x+19)/20個戰士,然后這些留下戰士就不能再去其它洞穴
  其他戰士可以繼續走去其它洞穴,可以選擇分組去不同的洞穴。
  戰士只能往洞穴深處走,不能走回頭路。
  問最多能獲得多少金子?

?

?

?

?思路:

  基礎的樹形DP。

  要特別注意的是,如果某個節點的bug數為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個,那么起碼拿到本節點的金子 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--) //到達本節點可能的人數。 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數、金子 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代碼

?

轉載于:https://www.cnblogs.com/xcw0754/p/4241459.html

總結

以上是生活随笔為你收集整理的HDU 1011 Starship Troopers星河战队(树形dp)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。