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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

[树形dp] Jzoj P1046 寻宝之旅

發布時間:2023/12/13 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [树形dp] Jzoj P1046 寻宝之旅 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Description

探險隊長凱因意外的弄到了一份黑暗森林的藏寶圖,于是,探險隊一行人便踏上了尋寶之旅,去尋找傳說中的寶藏。
藏寶點分布在黑暗森林的各處,每個點有一個值,表示藏寶的價值。它們之間由一些小路相連,小路不會形成環,即兩個寶藏點之間有且只有一條通路。探險隊從其中的一點出發,每次他們可以留一個人在此點開采寶藏,也可以不留,然后其余的人可以分成若干隊向這一點相鄰的點走去。需要注意的是,如果他們把隊伍分成兩隊或兩隊以上,就必須留一個人在當前點,提供聯絡和通訊,當然這個人也可以一邊開采此地的寶藏。并且,為了節約時間,隊伍在前往開采寶藏的過程中是不會走回頭路的。現在你作為隊長的助理,已經提供了這幅藏寶圖,請你算出探險隊所能開采的最大寶藏的價值。

Input

第一行有兩個正整數n(1<=n<=100),表示藏寶點的個數,m(1<=m=100)表示探險隊的人數。
第二行是n個不超過100的正整數,分別表示1到n每個點的寶藏價值。
接下來的n-1行,每行兩個數,x和y(1<=x,y<=n,x<>y),表示藏寶點x,y之間有一條路,數據保證不會有重復的路出現。
假設一開始探險隊在點1處。

Output

一個整數,表示探險隊所能獲得最大的寶藏價值。

Sample Input

5 3 1 3 7 2 8 1 2 2 3 1 4 4 5

?

?

題解

  • 又是一道樹形dp,今天題做的要死了
  • 題目說:
  • 它們之間由一些小路相連,小路不會形成環,即兩個寶藏點之間有且只有一條通路
  • 顯然就是棵樹
  • 容易得到設f[i][j]以i為根的子樹,剩j的的最大價值
  • 那就有兩種情況:
  • ①當前點不挖,直接跳
  • ②當前點留一個人挖,可以向下派j-1個人
  • 則有 f[i][j]=max(f[i][j],f[i][j-1-k]+f[son[i]][k]+v[i])
  • 那么我們不知道在f[i][j-1-k]中是否有v[i],如果有就算重了

  • 可以多定一個數組g,也可以多加一維,其實是一樣的

  • g[i][j]表示?]以i為根的子樹,剩j,不挖i 的的最大價值

代碼

1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 using namespace std; 5 int n,m,cnt,v[110],f[110][110],to[210],from[210],head[110],k[110],g[110][110]; 6 void insert(int x,int y) { to[++cnt]=y; from[cnt]=head[x]; head[x]=cnt; } 7 void dp(int root,int fa) 8 { 9 f[root][1]=v[root]; 10 for (int w=head[root];w;w=from[w]) 11 if (to[w]!=fa) 12 { 13 dp(to[w],root); 14 for (int i=1;i<=m;i++) k[i]=max(f[root][i],f[to[w]][i]); 15 for (int i=1;i<=m;i++) 16 for (int j=1;j<i;j++) 17 k[i]=max(k[i],g[root][i-j-1]+f[to[w]][j]+v[root]); 18 for (int i=1;i<=m;i++) f[root][i]=k[i]; 19 for (int i=1;i<=m;i++) k[i]=max(f[to[w]][i],g[root][i]); 20 for (int i=1;i<=m;i++) 21 for (int j=1;j<i;j++) 22 k[i]=max(k[i],g[root][i-j]+f[to[w]][j]); 23 for (int i=1;i<=m;i++) g[root][i]=k[i]; 24 } 25 } 26 int main() 27 { 28 scanf("%d%d",&n,&m); 29 for (int i=1;i<=n;i++) scanf("%d",&v[i]); 30 for (int i=1;i<=n-1;i++) 31 { 32 int x,y; 33 scanf("%d%d",&x,&y); 34 insert(x,y); insert(y,x); 35 } 36 dp(1,0); 37 printf("%d",f[1][m]); 38 return 0; 39 }

?

轉載于:https://www.cnblogs.com/Comfortable/p/9277479.html

總結

以上是生活随笔為你收集整理的[树形dp] Jzoj P1046 寻宝之旅的全部內容,希望文章能夠幫你解決所遇到的問題。

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