JDOJ-1310: VIJOS-P1144 小胖守皇宫

Posted oi-forever

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDOJ-1310: VIJOS-P1144 小胖守皇宫相关的知识,希望对你有一定的参考价值。

1310: VIJOS-P1144 小胖守皇宫

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 141  Solved: 64
[Submit][Status][Web Board]

Description

huyichen世子事件后,xuzhenyi成了皇上特聘的御前一品侍卫。 皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状;某些宫殿间可以互相望见。大内保卫森严,三步一岗,五步一哨,每个宫殿都要有人全天候看守,在不同的宫殿安排看守所需的费用不同。 可是xuzhenyi手上的经费不足,无论如何也没法在每个宫殿都安置留守侍卫。 帮助xuzhenyi布置侍卫,在看守全部宫殿的前提下,使得花费的经费最少。

Input

输入文件中数据表示一棵树,描述如下: 第1行  n,表示树中结点的数目。 第2行至第n+1行,每行描述每个宫殿结点信息,依次为:该宫殿结点标号i(0< i< =n),在该宫殿安置侍卫所需的经费k,该边的儿子数m,接下来m个数,分别是这个节点的m个儿子的标号r1,r2,...,rm。 对于一个n(0  <   n  < =  1500)个结点的树,结点标号在1到n之间,且标号不重复。

Output

输出文件仅包含一个数,为所求的最少的经费。

Sample Input

6 1 30 3 2 3 4 2 16 2 5 6 3 5 0 4 4 0 5 11 0 6 5 0

Sample Output

25

HINT

 

技术分享图片

总结:树形dp

dp[u][0] 被自己守
dp[u][1] 被父亲守
dp[u][2] 被儿子守

dp[u][0] += min(dp[v][1], min(dp[v][0], dp[v][2]));//儿子三种情况都可以

dp[u][1] += min(dp[v][0], dp[v][2]);//儿子只有这两种情况

for(枚举v)//枚举被哪个儿子守,利用已经计算好的dp[u][1]

dp[u][2] = min(dp[u][2], dp[u][1] - min(dp[v][0], dp[v][2]) + dp[v][0]);

 

初始化dp[u][0] = val[u], dp[u][2] = inf;

代码

#include<bits/stdc++.h>

using namespace std;
const int maxn = 3005;

int n, head[maxn], cnt = 1;

#define inf 10000007
int dp[maxn][3], val[maxn];
struct Node{
	int v, nxt;
} G[maxn];

void insert(int u, int v) {
	G[cnt] = (Node) {v, head[u]}; head[u] = cnt++;
} int in[maxn];
/*
dp[u][0] 被自己守
dp[u][1] 被父亲守
dp[u][2] 被儿子守
*/
void DP(int x) {
	dp[x][0] = val[x]; dp[x][2] = inf;
	for (int i = head[x]; i; i = G[i].nxt) {
		int v = G[i].v;
		DP(v); dp[x][0] += min(dp[v][1], min(dp[v][0], dp[v][2]));
		dp[x][1] += min(dp[v][0], dp[v][2]);
	} 
	for (int i = head[x]; i; i = G[i].nxt) {
		int v = G[i].v;
		dp[x][2] = min(dp[x][2], dp[x][1] - min(dp[v][0], dp[v][2]) + dp[v][0]);
	}
}

int main() {
	scanf("%d", &n);
	for (int i = 1; i <= n; ++i) {
		int x, m; scanf("%d", &x);
		scanf("%d%d", &val[x], &m);
		for (int j = 1; j <= m; ++j) {
			int y; scanf("%d", &y);
			insert(x, y); in[y]++;
		}
	}
	for (int i = 1; i <= n; ++i) {
		if(in[i] == 0) {
			DP(i);
		    printf("%d\n", min(dp[i][0], dp[i][2])); return 0;
		}
	}
	return 0;
}

  

以上是关于JDOJ-1310: VIJOS-P1144 小胖守皇宫的主要内容,如果未能解决你的问题,请参考以下文章

树形dp小胖守皇宫(vijosP1144)

小胖守皇宫(VIJOS P1144 )题解

Vijos1144小胖守皇宫树形DP

JDOJ-1260: VIJOS-P1083 小白逛公园

JDOJ-1194: VIJOS-P1009 清帝之惑之康熙

VIJOS-P1635 城市连接