Treedp入门问题—Anniversary party

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
 
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
2.解法思路

由参加宴会的人及其关系可以生成一棵树,利用动态规划从叶子节点返回到根节点,其中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;
}









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值