树形动态规划

问题可以分解成若干相互联系的阶段,在每一个阶段都要做出决策,全部过程的决策是一个决策序列。要使整个活动的总体效果达到最优的问题,称为多阶段决策问题。动态规划就是解决多阶段决策最优化问题的一种思想方法。

阶段

将所给问题的过程,按时间或空间特征分解成若干相互联系的阶段,以便按次序去求每阶段的解

状态

各阶段开始时的客观条件叫做状态。

决策

当各段的状态取定以后,就可以做出不同的决定,从而确定下一阶段的状态,这种决定称为决策。

策略

由开始到终点的全过程中,由每段决策组成的决策序列称为全过程策略,简称策略。

状态转移方程

前一阶段的终点就是后一阶段的起点,前一阶段的决策选择导出了后一阶段的状态,这种关系描述了由k阶段到k+1阶段状态的演变规律,称为状态转移方程。

目标函数与最优化概念

目标函数是衡量多阶段决策过程优劣的准则。最优化概念是在一定条件下找到一个途径,经过按题目具体性质所确定的运算以后,使全过程的总效益达到最优。

大多数动规都是在一维二维这种规则的背景下的,可以解决的问题比较局限,而树作为一种特殊的图,可以描述比较复杂的关系,再加上树的递归定义,是一种非常合适动规的框架,树型动态规划就成为动规中很特殊的一种类型。

树形动态规划基本上可以分为2个部分,一个是建树,另一个就是动态规划,一个好的数据结构,能使你编程非常容易,这也是树形动态规划的难点之一

典型例题

没有上司的晚会等

【问题描述】

有个公司要举行一场晚会。为了让到会的每个人不受他的直接上司约束而能玩得开心,公司领导决定:如果邀请了某个人,那么一定不会再邀请他的直接的上司,但该人的上司的上司,上司的上司的上司……都可以邀请。已知每个人最多有唯一的一个上司。

已知公司的每个人参加晚会都能为晚会增添一些气氛,求一个邀请方案,使气氛值的和最大。

【输入:】

第1行一个整数N(1<=N<=6000)表示公司的人数。

接下来N行每行一个整数。第i行的数表示第i个人的气氛值x(-128<=x<=127)。

接下来每行两个整数L,K。表示第K个人是第L个人的上司。

输入以0 0结束。

【输出】:

一个数,最大的气氛值和。

【样例输入】

7

1

1

1

1

1

1

1

1 3

2 3

6 4

7 4

4 5

3 5

0 0

【样例输出】

5

【分析】

如上例,上司与小兵之间的关系构成一棵树。

5

| \

3 4

| \ | \

1 2 6 7

又是求最优解,并且每一个节点的取舍关乎到全局 因此,此题可用树形动态规划

我们可用f[v][0]存储不选编号为V的节点的最优解,f[v][1]存储选编号为V的节点的最优解

//大数组的定义最好不要写在函数里,这样会使函数栈控件不足 

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define M 1000	//数组最大长度 

int shu[M][M],xb[M][M],shs[M],qf[M],f[M][2];
int main()
{

	int i,j,l,k,n,maxlev,s,x,a,b;

	memset(shu,0,sizeof(shu));
	memset(xb,0,sizeof(xb));
	memset(shs,0,sizeof(shs));
	memset(f,0,sizeof(f));

	//1、建树
	scanf("%d",&n);
	for(i=1;i<=n;i++)scanf("%d",&qf[i]);

	l=k=1;
	while(l&&k)
	{
		scanf("%d%d",&l,&k);
		shs[l]=k;
		xb[k][0]++;
		xb[k][xb[k][0]]=l;
	}

	maxlev=-1;
	for(i=1;i<=n;i++)
	{
		x=shs[i],s=1;
		while(x!=0){s++;x=shs[x];}
		shu[s][0]++;
		shu[s][shu[s][0]]=i;
		if(s>maxlev)maxlev=s;
	}

	//2、动态规划
	 for(i=maxlev;i>0;i--)
	 {
	 	for(j=1;j<=shu[i][0];j++)
	 	{
	 		if(xb[shu[i][j]][0]==0)
	 		{
	 			f[shu[i][j]][0]=0;
	 			f[shu[i][j]][1]=qf[shu[i][j]];
	 		}
	 		else
	 		{
	 			f[shu[i][j]][0]=0;
	 			f[shu[i][j]][1]=qf[shu[i][j]];
	 			for(k=1;k<=xb[shu[i][j]][0];k++)
	 			{
	 				a=f[xb[shu[i][j]][k]][0];b=f[xb[shu[i][j]][k]][1];

	 				f[shu[i][j]][1] +=a;//如果要当前节点,则不能取下部节点 

	 				//如果不要当前节点,则可要可不要下部节点,取使得气氛值最大的方案
					if(b>a)a=b;
	 				f[shu[i][j]][0] +=a;
	 			}
	 		}//状态转移
	 	}
	 }

	 s=0;
	 for(i=1;i<=shu[1][0];i++)//从树根获取最优方案
	 {
	 	a=f[shu[1][i]][0];b=f[shu[1][i]][1];
	 	if(b>a)a=b;
	 	s+=a;
	 }

	 printf("最大气氛值:%d\n",s); 

	return 0;
}
时间: 2024-12-15 13:43:10

树形动态规划的相关文章

Facebook Hacker Cup 2015 Round 1--Corporate Gifting(树形动态规划)

原题:https://www.facebook.com/hackercup/problems.php?pid=759650454070547&round=344496159068801 题意:给定一颗有根树,在树上下层的节点要给上层节点礼物,根节点的礼物则给慈善会,但是给礼物有个条件就是你不能送你的父节点已经送出的礼物.问满足要求的最少花费. 题解:这个题卡了一段时间,类似于染色问题,可以用树形动态规划求解.因为已知节点个数为N,则我们单个节点的最大花费不会超过log2(N) = 18. 1.

树形动态规划练习《蓝桥杯 结点选择》

问题描述 有一棵 n 个节点的树,树上每个节点都有一个正整数权值.如果一个点被选择了,那么在树上和它相邻的点都不能被选择.求选出的点的权值和最大是多少? 输入格式 第一行包含一个整数 n . 接下来的一行包含 n 个正整数,第 i 个正整数代表点 i 的权值. 接下来一共 n-1 行,每行描述树上的一条边. 输出格式 输出一个整数,代表选出的点的权值和的最大值. 样例输入 51 2 3 4 51 21 32 42 5 样例输出 12 样例说明 选择3.4.5号点,权值和为 3+4+5 = 12

bzoj 4033 树上染色 - 树形动态规划

有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑 色,并将其他的N-K个点染成白色.将所有点染色后,你会获得黑点两两之间的距离加上白点两两之间距离的和的 收益.问收益最大值是多少. Input 第一行两个整数N,K. 接下来N-1行每行三个正整数fr,to,dis,表示该树中存在一条长度为dis的边(fr,to). 输入保证所有点之间是联通的. N<=2000,0<=K<=N Output 输出一个正整数,表示收益的最大值. Sampl

结点选择 (蓝桥杯 树形动态规划)

问题描述 有一棵 n 个节点的树,树上每个节点都有一个正整数权值.如果一个点被选择了,那么在树上和它相邻的点都不能被选择.求选出的点的权值和最大是多少? 输入格式 第一行包含一个整数 n . 接下来的一行包含 n 个正整数,第 i 个正整数代表点 i 的权值. 接下来一共 n-1 行,每行描述树上的一条边. 输出格式 输出一个整数,代表选出的点的权值和的最大值. 样例输入 51 2 3 4 51 21 32 42 5 样例输出 12 样例说明 选择3.4.5号点,权值和为 3+4+5 = 12

Codeforces 1000G Two-Paths 树形动态规划 LCA

原文链接https://www.cnblogs.com/zhouzhendong/p/9246484.html 题目传送门 - Codeforces 1000G Two-Paths 题意 给定一棵有 $n(2\leq n\leq 3\times 10^5)$ 个节点的树,其中节点 $i$ 有权值 $a_i$,边 $e$ 有权值 $w_e$.$(1\leq a_i,w_e\leq 10^9)$ 现在给出 $q(1\leq q\leq 4\times 10^5)$ 组询问,每组询问给定两个数 $x,

树形动态规划 fjutoj-2392 聚会的快乐

聚会的快乐 TimeLimit:1000MS  MemoryLimit:128MB 64-bit integer IO format:%lld Problem Description 你要组织一个由你公司的人参加的聚会.你希望聚会非常愉快,尽可能多地找些有趣的热闹.但是劝你不要同时邀请某个人和他的上司,因为这可能带来争吵.给定N个人(姓名,他幽默的系数,以及他上司的名字),编程找到能使幽默系数和最大的若干个人. Input 第一行一个整数N(N<100).接下来有N行,每一行描述一个人的信息,信

树形动态规划 fjutoj-2131 第四集,聚集城市

第四集,聚集城市 TimeLimit:1000MS  MemoryLimit:128MB 64-bit integer IO format:%lld Problem Description 在小A解读完手机信息后,得到了特工们的位置情报以及他们最近将会又一次聚会(除了谈论了关于抓捕小A和小C的事情外,主要谈论了关于走私事情-) 因为小C原本是他们的内部人员,所以她知道这个组织有一个习惯,即特工们每次选择聚会的城市,他们都会选择使所有组员所在市距离聚会城市的路程的和最小的城市,而且每个城市最多有一

codevs 1380 没有上司的舞会 - 树形动态规划

题目描述 Description Ural大学有N个职员,编号为1~N.他们有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司.每个职员有一个快乐指数.现在有个周年庆宴会,要求与会职员的快乐指数最大.但是,没有职员愿和直接上司一起与会. 输入描述 Input Description 第一行一个整数N.(1<=N<=6000)接下来N行,第i+1行表示i号职员的快乐指数Ri.(-128<=Ri<=127)接下来N-1行,每行输入一对整数L,K.表示K是L

树形动态规划专题

1.OJ1278战略游戏 f[u][0]代表以u为根的子树,u不放时,最少放置节点数. f[u][1]代表以u为根的子树,u放时,最少放置节点数. f[u][0]=Σf[son][1]. f[u][1]=Σmin(f[son][1],f[son][0]). ans=min(f[root][0],f[root][1]). #include<cstdio> #include<iostream> using namespace std; const int maxn=1500; int