人品问题
Posted hbhszxyb
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了人品问题相关的知识,希望对你有一定的参考价值。
人品问题( 树型dp(star?))
- 时限:(1s) 内存:(10M)
Descrption
- 网上出现了一种高科技产品——人品测试器。只要你把你的真实姓名输入进去,系统将自动输出你的人品指数。把儿不相信自己的人品为 (0) 。
- 经过了许多研究后,把儿得出了一个更为科学的人品计算方法。这种方法的理论依据是一个非常重要的结论:人品具有遗传性。一个人的人品完全由他的祖先决定。
- 把儿提出的人品计算方法相当简单,只需要将测试对象的 (k) 个祖先的人品指数(可能为负数)加起来即可。选择哪 (k) 个祖先可以由测试者自己决定,但必须要满足这个要求:如果除自己的父母之外的某个祖先被选了,那么他的下一代必需要选(不允许跳过某一代选择更远的祖先,否则将失去遗传的意义)。
- 非常不幸的是,把儿测试了若干次,他的人品值仍然不能为一个正数。现在把儿需要你帮助他找到选择祖先的最优方案,使得他的人品值最大。
Input
- 第一行是两个用空格隔开的正整数 (n) 和 (k),其中 (n) 代表把儿已知的家谱中共有多少人(包括把儿本身在内),(k) 的意义参见问题描述。
- 数据的第二行有 (n-1) 个用空格隔开的整数(可能为负),这些数的绝对值在 (2^{15}) 以内。其中,第 (i) 个数表示编号为 (i+1) 的人的人品值。我们规定,编号为 (1) 的人是把儿。
- 接下来 (n) 行每行有两个用空格隔开的数,其中第 (i) 行的两个数分别表示第 (i) 个人的父亲和母亲的编号。如果某个人的父亲或母亲不在这个家谱内,则在表示他的父亲或母亲的编号时用 (0) 代替。
- 输入数据中除把儿以外的所有人都是把儿的祖先,他们都会在输入数据中作为父亲或母亲被描述到。输入数据中每个人都不可能同时作为多个人的父亲或者是母亲。
Output
- 输出只有一行,为把儿能够得到的最大人品值
Sample Input
6 3
-2 3 -2 3 -1
2 3
4 5
0 6
0 0
0 0
0 0
Sample Output
4
Hint
- 显然,选择祖先(2,3,5)能使把儿的人品值达到最大。这个最大值为 (4) 。
- 对于 (50\%) 的数据,(n<=10);
- 对于(100\%) 的数据,(n<=100)。
- 来源:
分析
- 典型的基础树归。
Code
#include <bits/stdc++.h>
const int maxn=100+5,Inf=0x3f3f3f3f;
struct Edge{int mum,dad,rp;}e[maxn];
bool vis[maxn][maxn];//记忆化用,因为人品值可负可正,需要一个数组来标记状态
int dp[maxn][maxn],n,k;
int dfs(int u,int cnt){//u为根的子树选cnt个节点
if(vis[u][cnt])return dp[u][cnt];//记忆化
if(!cnt)return dp[u][cnt]=0;//一个都不选人品为0
if(!u)return dp[u][cnt]=-Inf;//u==0表示为空
if(cnt==1)return dp[u][cnt]=e[u].rp;//只选一个选根就行
int ans=-Inf;
for(int i=0;i<cnt;++i)//枚举左右子树选的个数
ans=std::max(ans,e[u].rp+dfs(e[u].mum,i)+dfs(e[u].dad,cnt-i-1));
vis[u][cnt]=1;
return dp[u][cnt]=ans;
}
void Solve(){
scanf("%d%d",&n,&k);
for(int i=2;i<=n;++i)
scanf("%d",&e[i].rp);
for(int i=1;i<=n;++i)
scanf("%d%d",&e[i].mum,&e[i].dad);
printf("%d
",dfs(1,k+1));
}
int main() {
Solve();
return 0;
}
以上是关于人品问题的主要内容,如果未能解决你的问题,请参考以下文章