Treedp入门问题—Anniversary party
今天看到树形动态规划的入门问题——Anniversary party,这个问题的思路比较简单,只是实现过程稍微有些麻烦,我看网上的大部分代码,由于注释较少作为新手可能不太容易懂,便自己写了一个带有详细注释的C++实现代码,大家有需要可以参考一下。
1.题目
某公司要举办一次晚会,但是为了使得晚会的气氛更加活跃,每个参加晚会的人都不希望在晚会中见到他的直接上司,现在已知每个人的活跃指数和上司关系(当然不可能存在环),求邀请哪些人(多少人)来能使得晚会的总活跃指数最大。
Input
Employees are numbered from 1 to N. A first line of input contains a number N. 1 <= N <= 6 000. Each of the subsequent N lines contains the conviviality rating of the corresponding employee. Conviviality rating is an integer number in a range from -128 to 127. After that go T lines that describe a supervisor relation tree. Each line of the tree specification has the form:
L K
It means that the K-th employee is an immediate supervisor of the L-th employee. Input is ended with the line
0 0
L K
It means that the K-th employee is an immediate supervisor of the L-th employee. Input is ended with the line
0 0
Output
Output should contain the maximal sum of guests' ratings.
Sample Input
7 1 1 1 1 1 1 1 1 3 2 3 6 4 7 4 4 5 3 5 0 0
Sample Output
5
由参加宴会的人及其关系可以生成一棵树,利用动态规划从叶子节点返回到根节点,其中dp[i][0]表示第i个节点不参加宴会的愉悦度,dp[i][1]表示第i个节点参加宴会的愉悦度
状态转换方程
dp[i][0]+=max{dp[j][0],dp[j][1]};
dp[i][1]+=max{dp[j][0]};其中j节点为i节点的子节点
3.C++代码实现
#include<iostream>
#include<vector>
using namespace std;
struct node//树节点
{
bool flag;//用于标记该节点是否是根节点
vector<node> vecnode;//用于存放每个几点的子几点
int dp[2];//dp[1]表示该节点参加宴会的愉悦度;dp[0]表示该节点不参加宴会的愉悦度
};
int max(int a,int b)
{
return a>b?a:b;
}
//treedp函数用动态从叶子节点到根节点求解宴会的最大愉悦程度
void treedp(node &root)
{
//如果该节点是叶子节点,直接返回
if(0==root.vecnode.size())
return;
//递归求解每个节点的愉悦度
for(vector<node>::iterator iter=root.vecnode.begin();iter!=root.vecnode.end();iter++)
{
treedp(*iter);
//状态转换方程
root.dp[0]+=max((*iter).dp[0],(*iter).dp[1]);
root.dp[1]+=(*iter).dp[0];
}
}
int main()
{
int n;
cin>>n;
node *N=new node[n];
//初始化
for(int i=0;i<n;i++)
{
N[i].flag=true;
}
for(int i=0;i<n;i++)
{
cin>>N[i].dp[1];
N[i].dp[0]=0;
}
int parent,child;
//输入宴会参与者的关系
for(int i=0;i<n-1;i++)
{
cin>>child>>parent;
N[parent-1].vecnode.push_back(N[child-1]);
N[child-1].flag=false;
}
node root;
//寻找根节点
for(int i=0;i<n;i++)
if(true==N[i].flag)
root=N[i];
//求解宴会最大愉悦度
treedp(root);
cout<<max(root.dp[0],root.dp[1])<<endl;
}