[树形dp] Jzoj P3914 人品问题
生活随笔
收集整理的這篇文章主要介紹了
[树形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 人品问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Python3爬虫】为什么你的博客没人
- 下一篇: 做梦梦到自己是什么意思