HDU-4276 The Ghost Blows Light (树形DP+背包)

题目大意:在一个n个节点的树形迷宫中,1为起点,n为出口。每个节点上有一定价值的珠宝,在节点之间移动的时间已知,问在能走出迷宫的前提下并且不超过m的时间内能收集的最多珠宝是多少?

题目分析:在树上,从1到n的路径唯一。从1到n的唯一路径叫做主线路,要想走到出口,一定会经过主线路,也就是必须经过主线路上节点。在脱离主线路之前必须要预留出返回的时间。

 

代码如下:

# include<iostream>
# include<cstdio>
# include<vector>
# include<queue>
# include<cstring>
# include<algorithm>
using namespace std;

const int N=105;
const int INF=1000000000;

int n,m;
int d[N];
int dp[N][N*5];
int g[N][N];
int w[N],pre[N];
vector<int>e[N];

void init()
{
	int a,b,c;
	for(int i=1;i<=n;++i)
		e[i].clear();
	for(int i=1;i<n;++i){
		scanf("%d%d%d",&a,&b,&c);
		g[a][b]=g[b][a]=c;
		e[a].push_back(b);
		e[b].push_back(a);
	}
	for(int i=1;i<=n;++i)
		scanf("%d",w+i);
}

void spfa()
{
	fill(pre,pre+n+1,-1);
	fill(d+1,d+n+1,INF);
	queue<int>q;
	q.push(1);
	d[1]=0;
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		for(int i=0;i<e[u].size();++i){
			int v=e[u][i];
			if(d[v]>d[u]+g[u][v]){
				d[v]=d[u]+g[u][v];
				pre[v]=u;
				q.push(v);
			}
		}
	}
}

void dfs(int u,int fa)
{
	fill(dp[u],dp[u]+m+1,w[u]);
	for(int i=0;i<e[u].size();++i){
		int v=e[u][i];
		if(v==fa) continue;
		dfs(v,u);
		
		int t=2*g[u][v];
		
		for(int j=m;j>=t;--j)
			for(int k=0;k+t<=j;++k)
				dp[u][j]=max(dp[u][j],dp[v][k]+dp[u][j-k-t]);
	}
}

void solve()
{
	spfa();
	if(d[n]>m){
		printf("Human beings die in pursuit of wealth, and birds die in pursuit of food!\n");
	}else{
		int u=n;
		while(pre[u]!=-1){
			g[pre[u]][u]=g[u][pre[u]]=0;
			u=pre[u];
		}
		m-=d[n];
		dfs(1,-1);
		printf("%d\n",dp[1][m]);
	}
}

int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		init();
		solve();
	}
	return 0;
}

  

posted @ 2016-04-09 17:02  20143605  阅读(321)  评论(0编辑  收藏  举报