现在的位置: 首页 > 综合 > 正文

HDU 4276 树形dp + 背包

2013年11月10日 ⁄ 综合 ⁄ 共 1922字 ⁄ 字号 评论关闭

题意:

n 个点 maxtime的时间

下面给定一棵树及走过该边需要的时间

最后一行给定 每个点的宝藏价值

 

问在maxtime时间内能否 从 1->n ,若能输出最多能获得的宝藏价值

 

思路:

对于树,除了1->n的路径, 若去其他点则要走回头路

所以我们可以先走到终点, 最后时间 - 1-n路径花费的时间, 再把该路径的边花费改为0

这样就是 剩下时间 ,走非路径上点 能获得的最高价值,就是背包问题

 

dp[i][j] 表示 i 点用了  j 时刻能获得的最大价值

先用spfa跑出1-n的路径,再修改路径上的边权, 树形背包一下 结果就是 dp[1][maxtime]

 

 

 

 

 

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string>
#include<queue>
#include<string.h>
#include<map>
#include<set>
#include<stack>
#include<vector>
#include<math.h>
#define inf 10000000
#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define Mid(x,y) ((x+y)>>1)
#define ll int
using namespace std;
inline ll Min(ll a,ll b){return a>b?b:a;}
inline ll Max(ll a,ll b){return a<b?b:a;}
#define N 105
struct Edge{
	int from, to, dis, nex;
}edge[N<<1];
int head[N], edgenum;
void addedge(int u, int v, int d){
	Edge E={u, v, d, head[u]};
	edge[ edgenum ] = E;
	head[u] = edgenum++;
}
int maxtime, n, a[N];
int pre[N], dis[N];
void spfa(){
	queue<int>q;
	q.push(1);
	memset(dis, -1, sizeof(dis));
	dis[1] = 0;
	pre[1] = -1;
	while(!q.empty()){
		int u = q.front(); q.pop();
		for(int i = head[u]; i !=-1;i = edge[i].nex){
			int v = edge[i].to;
			if(dis[v] == -1)
			{
				dis[v] = dis[u] + edge[i].dis;
				pre[v] = u;
				q.push(v);
			}
		}
	}
}
int dp[N][505];
void dfs(int u, int fa){
	for(int i = 0;i <= maxtime; i++)dp[u][i] = a[u];
	for(int i = head[u]; ~i; i =edge[i].nex)
	{
		int v = edge[i].to;
		if(v != fa)
		{
			dfs(v, u);
			int cost = edge[i].dis<<1;
			for(int j = maxtime; j>= cost; j--)
			{
				for(int k = 0; k<= j - cost; k++)
					dp[u][j] = Max(dp[u][j], dp[v][k] + dp[u][j-cost-k]);
			}
		}
	}
}
bool Islian[N];

int main(){
	ll i, u, v, d, j;

	while(~scanf("%d %d",&n,&maxtime)){
		memset(Islian, 0, sizeof(Islian));
		memset(head, -1, sizeof(head)); edgenum = 0;
		memset(dp, 0, sizeof(dp));

		for(i=1;i<n;i++){
			scanf("%d %d %d",&u,&v,&d);
			addedge(u, v, d);
			addedge(v, u, d);
		}
		for(i=1;i<=n;i++)scanf("%d",&a[i]);

		spfa();
		if(dis[n] == -1 || dis[n]>maxtime)
		{printf("Human beings die in pursuit of wealth, and birds die in pursuit of food!\n");continue;}
		i = n;
		while(i!=-1)
		{
			Islian[i] = true;
			i = pre[i];
		}
		i = n;
		while(i!=-1)
		{
			for(j=head[i];j!=-1;j=edge[j].nex)
				if(Islian[ edge[j].to ])
					edge[j].dis = 0;
			i = pre[i];
		}

		maxtime -= dis[n];
		dfs(1,-1);
		printf("%d\n",dp[1][maxtime]);
	}
	return 0;
}

 

抱歉!评论已关闭.