#树形dp#jzoj 2005 皇宫看守

本文介绍了一种解决宫殿守卫问题的动态规划算法。该问题的目标是在确保所有宫殿都有守卫可见的前提下,最小化所需的守卫数量。通过定义状态f[i][0/1/2]来表示不同情况下以节点i为根的子树所需最少守卫数,并给出了具体的转移方程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

宫殿间可以相互看见,在看守全部宫殿的前提下,使花费的经费最少。


分析

f[i][0]表示i节点在父节点可看到时,以i为根的子树需要安排的最少士兵数f[i][0]表示i节点在父节点可看到时,以i为根的子树需要安排的最少士兵数f[i][0]ii
f[i][1]表示i节点在子节点可看到时,以i为根的子树需要安排的最少士兵数f[i][1]表示i节点在子节点可看到时,以i为根的子树需要安排的最少士兵数f[i][1]ii
f[i][2]表示i节点安装士兵时,以i为根的子树需要安排的最少士兵数f[i][2]表示i节点安装士兵时,以i为根的子树需要安排的最少士兵数f[i][2]ii
f[i][0]=min(f[son][1],f[son][2]),f[i][1]=min(f[son][1],f[son][2])+df[i][0]=min(f[son][1],f[son][2]),f[i][1]=min(f[son][1],f[son][2])+df[i][0]=min(f[son][1],f[son][2]),f[i][1]=min(f[son][1],f[son][2])+d
f[i][2]=min(f[son][0],f[son][1],f[son][2])+cost[i]f[i][2]=min(f[son][0],f[son][1],f[son][2])+cost[i]f[i][2]=min(f[son][0],f[son][1],f[son][2])+cost[i]
d=min(f[son][2]−min(f[son][1],f[son][2]))d=min(f[son][2]-min(f[son][1],f[son][2]))d=min(f[son][2]min(f[son][1],f[son][2]))


代码

#include <cstdio>
#include <cctype>
using namespace std;
struct node{int y,next;}e[4001]; int ls[1501]; bool v[1501];
int n,k,f[1501][3],m,root,x,y,cost[1501];
int in(){
	int ans=0; char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=ans*10+c-48,c=getchar();
	return ans;
}
int min(int a,int b){return (a<b)?a:b;}
void dp(int x,int last){
	int d=1e7;
	for (int i=ls[x];i;i=e[i].next){
		if (e[i].y==last) continue;//不退回去
		dp(e[i].y,x);
		f[x][0]+=min(f[e[i].y][1],f[e[i].y][2]);
		f[x][1]+=min(f[e[i].y][1],f[e[i].y][2]);
		d=min(d,f[e[i].y][2]-min(f[e[i].y][2],f[e[i].y][1]));
		f[x][2]+=min(f[e[i].y][2],min(f[e[i].y][0],f[e[i].y][1]));
	}
	f[x][1]+=d; f[x][2]+=cost[x];
}
int main(){
	freopen("guard.in","r",stdin);
	freopen("guard.out","w",stdout);
	n=in();
	for (int i=1;i<=n;i++){
		x=in(); cost[x]=in(); k=in();
		while (k--) e[++m]=(node){y=in(),ls[x]},ls[x]=m,v[y]=1;
	}
	for (root=1;root<=n&&v[root];root++);
	dp(root,0); return !printf("%d",min(f[root][1],f[root][2]));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值