vijos1144.小胖守皇宫(树形DP)

原创 2015年11月20日 10:05:36

一棵树有 N 个节点,现在需要将所有节点都看守住,如果我们选择了节点 i,那么节点 i 本身,节点 i 的父亲和儿子都会被看守住,每个节点有一个选择代价,求完成任务所需要的最小的代价。

显然这是一道树形DP。根据每个节点其实有只有三个状态:①被自己看守;②被儿子看守;③被父亲看守。我们设这三种状态分别为 F1,F2,F3。当然最终作为答案的根节点没有父亲就从 F1,F2 里面选小的。

接下来我们要考虑怎么转移。首先看 F1,我们规定 F1[ i ] 代表的是 i 节点被自己看守且以 i 为根的子树都已被看守的最小代价,也就是说一定会选择 i 节点自己,答案中必定会加入选择他自己的代价 Wi。因为这个点会被自己看管,所以只要考虑在其儿子的三个状态中选一个最小的,保证这个节点下面的子树都已被看守就行了。所以 F1[ i ] += min{ F1[ Si ], F2[ Si ], F3[ Si ] } + w[ i ],其中 Si 代表 i 节点的儿子。

接下来看 F2,我们规定 F2[ i ] 代表 i 节点被儿子看守且以 i 为根的子树都已被看守的最小代价,也就是说一定不选 i 节点,但是至少要在 i 节点的儿子中选择一个而且最多也就选一个,因为代价是正数,选一个就能把 i 看住,就不需要选择多余的点在增加代价了。因为 i 节点不能被选,所以只能在其儿子的 F1, F2 状态中选择小的( F3[ Si ] 代表选择 i 节点,所以不能用 F3[ Si ] ),来保证其子树都已被看守。所以 F2[ i ] += min{ F1[ Si ], F2[ Si ] } + tt 代表选择一个儿子的最小代价:t = F1[ Si ] - min{ F1[ Si ], F2[ Si ] },顺便解释一下 t 的转移:我们从 Si 被看管的代价中选一个最小的,如果是 F1,那么说明 Si 已经被选,就不用再加 W[ Si ] 了,如果是 F2, 那么 F1 - F2 = W[ i ]。 

最后看 F3,我们规定 F3[ i ] 代表 i 节点被父亲看守且以 i 为根的子树都已经被看守的最小代价,也就是说一定不选 i 节点和其儿子节点,必须选择他的父亲。因为必须选择父亲,那么 i 一定会被父亲看守,那么我们只要保证其下面的子树都已被看守,就是在儿子的 F1, F2 中选一个小的,因为还是不能选 i,所以其儿子的 F3 状态仍然不用考虑。所以 F3[ i ] += min{ F1[ Si ], F2[ Si ]}

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int MAX_N = 1505;

int n, num[MAX_N], w[MAX_N], s[MAX_N][MAX_N];
int g[MAX_N];
int f1[MAX_N], f2[MAX_N], f3[MAX_N];

void init()
{
	scanf("%d", &n);
	for (int i = 1; i <= n; i ++){
		int x; scanf("%d", &x); 
		scanf("%d%d", &w[x], &num[x]);
		for (int j = 1; j <= num[x]; j ++){
			int y; scanf("%d", &y);
			g[y] = x; s[x][j] = y;
		} 
	}
}

void dfs(int x)
{
	int p = 0x7fffffff;
	f1[x] = f2[x] = f3[x] = 0;
	for (int i = 1; i <= num[x]; i ++){
		dfs(s[x][i]);
		f1[x] += min(f1[s[x][i]], min(f2[s[x][i]], f3[s[x][i]]));
		f2[x] += min(f1[s[x][i]], f2[s[x][i]]);
		int t = f1[s[x][i]] - min(f1[s[x][i]], f2[s[x][i]]);
		p = min(p, t);
		f3[x] += min(f1[s[x][i]], f2[s[x][i]]); 
	}
	f2[x] += p; f1[x] += w[x];
}

void doit()
{
	memset(f1, 127, sizeof(f1)); memset(f2, 127, sizeof(f2));
	memset(f3, 127, sizeof(f3));
	int ans = 0;
	for (int i = 1; i <= n; i ++){
		if (!g[i]){
			dfs(i);
			ans += min(f1[i], f2[i]);
		}
	}
	printf("%d\n", ans);
}

int main()
{
	init();
	doit();
	return 0;
}

 

版权声明:本文为博主原创文章,未经博主允许不得转载。

VIJOS-P1144 小胖守皇宫

VIJOS-P1144 小胖守皇宫Descriptionhuyichen世子事件后,xuzhenyi成了皇上特聘的御前一品侍卫。 皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状;某些宫殿间可以...
  • Z_Mendez
  • Z_Mendez
  • 2015年08月05日 18:12
  • 1453

VIJOS P1144 小胖守皇宫

描述 huyichen世子事件后,xuzhenyi成了皇上特聘的御前一品侍卫。 皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状;某些宫殿间可以互相望见。大内保卫森严,三步一岗,五步一哨,每个...
  • dongdongzhang_
  • dongdongzhang_
  • 2013年08月12日 21:56
  • 2491

BZOJ 2152 聪聪可可 树的点分治/树形DP

题目大意:给定一棵树,每条边上有边权,求距离为3的倍数的有序点对 树的点分治,对于每个重心统计出每棵子树距离重心长度为0/1/2的点的数量,计算出ans即可 最后ans*2+1 和n^2进行一下约...
  • PoPoQQQ
  • PoPoQQQ
  • 2014年10月27日 10:11
  • 2635

Vijos 1144 小胖守皇宫 [树形dp]

P1144小胖守皇宫描述 huyichen世子事件后,xuzhenyi成了皇上特聘的御前一品侍卫。 皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状;某些宫殿间可以互相望见。大内保卫森严,三...
  • ourfutr2330
  • ourfutr2330
  • 2016年08月01日 18:50
  • 577

Vijos 1144 小胖守皇宫 【树形DP】

小胖守皇宫 描述 huyichen世子事件后,xuzhenyi成了皇上特聘的御前一品侍卫。 皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状;某些宫殿间可以互相望见。大...
  • u010568270
  • u010568270
  • 2017年03月23日 16:09
  • 294

VIJOS-P1144 小胖守皇宫(树形dp)

对于每一个节点,有3种状态:自己守自己,被儿子守,被父亲守;每次用儿子更新父节点。 设f [st][0]表示被自己守,它的儿子三种状态都可以; f[st][2]表示被父亲守,那么这个节点不能守它的...
  • KatnissJ
  • KatnissJ
  • 2015年08月05日 20:49
  • 608

较难树形动态规划(Vijos 1144 小胖守皇宫/皇宫看守)

vijos 1144 小胖守皇宫/皇宫看守 树形一维三状态DP 考虑后效性的问题
  • qq_36038511
  • qq_36038511
  • 2017年03月22日 14:01
  • 225

VIJOS-P1144 小胖守皇宫

VIJOS-P1144 小胖守皇宫Descriptionhuyichen世子事件后,xuzhenyi成了皇上特聘的御前一品侍卫。 皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状;某些宫殿间可以...
  • Z_Mendez
  • Z_Mendez
  • 2015年08月05日 18:12
  • 1453

VIJOS P1144 小胖守皇宫

描述 huyichen世子事件后,xuzhenyi成了皇上特聘的御前一品侍卫。 皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状;某些宫殿间可以互相望见。大内保卫森严,三步一岗,五步一哨,每个...
  • dongdongzhang_
  • dongdongzhang_
  • 2013年08月12日 21:56
  • 2491

【解题报告】小胖守皇宫

【树形DP】小胖守皇宫题目来源:Vijos1144。根据题意,此题要求求最优值,并且按照从叶向根这个决策顺序来看,后面的决策不会影响到前面的决策(对此句有疑问可接着往下看),满足无后效性。因此姑且套用...
  • TengWan_Alunl
  • TengWan_Alunl
  • 2017年07月08日 21:30
  • 176
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:vijos1144.小胖守皇宫(树形DP)
举报原因:
原因补充:

(最多只允许输入30个字)