洛谷P2458 [SDOI2006]保安站崗 題解(樹上dp,巧妙,動態規劃,較難)

solution:

dp[u][0 2]dp[u][0~2]

0:u0:點u處站了一個保安

dp[u][0]=a[u]dp[u][0]=a[u]
dp[u][0]+=min(dp[v][0 2])dp[u][0]+=min(dp[v][0~2])

2:uu2:點u處沒有站保安,點u靠父親來安保
dp[u][2]+=min(dp[v][0 1])dp[u][2]+=min(dp[v][0~1])

1:uu1:點u處沒有站保安,點u靠某個兒子來安保
dp[u][1]+=min(dp[v][0 1])dp[u][1]+=min(dp[v][0~1])
便在計算的時候順便看一下
dp[u][1]==sigmadp[v][1]如果dp[u][1]==sigma dp[v][1]
dp[v][0]dp[v][1]找一個最小的dp[v][0]-dp[v][1]
dp[u][1]+=dp[v][0]dp[v][1]dp[u][1]+=dp[v][0]-dp[v][1]

:min(dp[root][0],dp[root][1])答案:min(dp[root][0], dp[root][1])

code:

/*
dp[u][0~2]

0:點u處站了一個保安

dp[u][0]=a[u]
dp[u][0]+=min(dp[v][0~2])

2:點u處沒有站保安,點u靠父親來安保
dp[u][2]+=min(dp[v][0~1])

1:點u處沒有站保安,點u靠某個兒子來安保
dp[u][1]+=min(dp[v][0~1])
在計算的時候順便看一下
如果dp[u][1]==sigma dp[v][1]
找一個最小的dp[v][0]-dp[v][1]
dp[u][1]+=dp[v][0]-dp[v][1]

答案:min(dp[root][0], dp[root][1])
*/ 

#include<cstdio>
#include<vector>
#include<algorithm> 
using namespace std;
int f[1505][5];
int val[1505];
vector<int>e[1505];
void TreeDp(int x,int fa)
{
	f[x][0]=val[x];
	int tag=0;
	int ls=1000000007;
	for(int i=0;i<e[x].size();i++)
	{
	
		int y=e[x][i];
		if(y==fa)continue;
		TreeDp(y,x);
		int tmp=min(f[y][0],f[y][1]);
		f[x][0]+=min(tmp,f[y][2]);
		f[x][2]+=tmp;
		if(f[y][0]<f[y][1])tag++;
		else
		{
			ls=min(ls,f[y][0]-f[y][1]);
		}
		f[x][1]+=tmp;
	}
	if(tag==0)
	{
		f[x][1]+=ls; 
	}
	return ;
}
int main()
{
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		int num,m,x;
		scanf("%d",&num);
		scanf("%d",&val[num]);
		scanf("%d",&m);
		for(int j=1;j<=m;j++)
		{
			scanf("%d",&x);
			e[num].push_back(x);
			e[x].push_back(num);
		}
	}
	TreeDp(1,0);
	printf("%d\n",min(f[1][0],f[1][1]));
	return 0;
}

發佈了391 篇原創文章 · 獲贊 167 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章