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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

[树形dp] Jzoj P3914 人品问题

發布時間:2023/11/29 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [树形dp] Jzoj P3914 人品问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Description

網上出現了一種高科技產品——人品測試器。只要你把你的真實姓名輸入進去,系統將自動輸出你的人品指數。yzx不相信自己的人品為0。經過了許多研究后,yzx得出了一個更為科學的人品計算方法。這種方法的理論依據是一個非常重要的結論:人品具有遺傳性。因此,一個人的人品完全由他的祖先決定。yzx提出的人品計算方法相當簡單,只需要將測試對象的k個祖先的人品指數(可能為負數)加起來即可。選擇哪k個祖先可以由測試者自己決定,但必須要滿足這個要求:如果除自己的父母之外的某個祖先被選了,那么他的下一代必需要選(不允許跳過某一代選擇更遠的祖先,否則將失去遺傳的意義)。
非常不幸的是,yzx測試了若干次,他的人品值仍然不能為一個正數。現在yzx需要你幫助他找到選擇祖先的最優方案,使得他的人品值最大。

Input

第一行是兩個用空格隔開的正整數n和k,其中n代表yzx已知的家譜中共有多少人(包括yzx本身在內),k的意義參見問題描述。
第二行有n-1個用空格隔開的整數(可能為負),這些數的絕對值在2^15以內。其中,第i個數表示編號為i+1的人的人品值。我們規定,編號為1的人是yzx。
接下來n行每行有兩個用空格隔開的數,其中第i行的兩個數分別表示第i個人的父親和母親的編號。如果某個人的父親或母親不在這個家譜內,則在表示他的父親或母親的編號時用0代替。
除yzx以外的所有人都是yzx的祖先,他們都會作為父親或母親被描述到。每個人都不可能同時作為多個人的父親或者是母親。

Output

一個整數,表示yzx能夠得到的最大人品值。

Sample Input

6?3
-2?3?-2?3?-1
2?3
4?5
0?6
0?0
0?0
0?0

Sample Output

4
樣例說明下圖顯示了輸入樣例所描述的家譜圖。括號里的數表示的是該人的人品值。
?
4(-2)??5(3)??6(-1)
???\???/?????/
????\?/?????/
???2(-2)???3(3)
??????\???/
???????\?/
???????1?<---yzx
?
顯然,選擇祖先2、3、5能使yzx的人品值達到最大。這個最大值為4,表示yzx能夠得到的最大人品值。

Data Constraint

50%的數據,n<=10。
100%的數據,n<=100。

?

題解

  • 這題顯然就是一個樹形dp
  • 設f[i][j]為在i為根的子樹里,選了j個祖先的最大人品值
  • 那么就可以枚舉左子樹里選祖先的個數i,然后右子樹里就是sum-i-1,因為還要包括自己
  • 然后取個max就好了

代碼

1 #include <cstdio> 2 #include <iostream> 3 #define N 210 4 #define inf 0x7ffffff 5 using namespace std; 6 struct edge { int x,y,v; }e[N]; 7 int n,k,p[N][N],f[N][N]; 8 int dp(int x,int sum) 9 { 10 if (p[x][sum]) return f[x][sum]; 11 if (!sum) return f[x][sum]=0; 12 if (!x) return f[x][sum]=-inf; 13 if (sum==1) return f[x][sum]=e[x].v; 14 int ans=-inf; 15 for (int i=0;i<sum;i++) ans=max(ans,e[x].v+dp(e[x].x,i)+dp(e[x].y,sum-i-1)); 16 p[x][sum]=1,f[x][sum]=ans; return ans; 17 } 18 int main() 19 { 20 scanf("%d%d",&n,&k); 21 for (int i=2;i<=n;i++) scanf("%d",&e[i].v); 22 for (int i=1;i<=n;i++) scanf("%d%d",&e[i].x,&e[i].y); 23 printf("%d",dp(1,k+1)); 24 }

?

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

總結

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

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