http://acm.hdu.edu.cn/showproblem.php?pid=4276
Problem Description
My name is Hu Bayi, robing an ancient tomb in Tibet. The tomb consists of N rooms (numbered from 1 to N) which are connected by some roads (pass each road should cost some time). There is exactly one route between any two rooms, and each room contains some treasures. Now I am located at the 1st room and the exit is located at the Nth room.
Suddenly, alert occurred! The tomb will topple down in T minutes, and I should reach exit room in T minutes. Human beings die in pursuit of wealth, and birds die in pursuit of food! Although it is life-threatening time, I also want to get treasure out as much as possible. Now I wonder the maximum number of treasures I can take out in T minutes.
Input
There are multiple test cases.
The first line contains two integer N and T. (1 <= n <= 100, 0 <= T <= 500)
Each of the next N - 1 lines contains three integers a, b, and t indicating there is a road between a and b which costs t minutes. (1<=a<=n, 1<=b<=n, a!=b, 0 <= t <= 100)
The last line contains N integers, which Ai indicating the number of treasure in the ith room. (0 <= Ai <= 100)
The first line contains two integer N and T. (1 <= n <= 100, 0 <= T <= 500)
Each of the next N - 1 lines contains three integers a, b, and t indicating there is a road between a and b which costs t minutes. (1<=a<=n, 1<=b<=n, a!=b, 0 <= t <= 100)
The last line contains N integers, which Ai indicating the number of treasure in the ith room. (0 <= Ai <= 100)
Output
For each test case, output an integer indicating the maximum number of treasures I can take out in T minutes; if I cannot get out of the tomb, please output "Human beings die in pursuit of wealth, and birds die in pursuit of food!".
Sample Input
5 10 1 2 2 2 3 2 2 5 3 3 4 3 1 2 3 4 5
Sample Output
11
Source
/**
hdu4276 树形dp
题目大意:给定一个n节点的树,从1到n去每条路耗费一定的时间,每经过一个点就可以获得这一点的能量值,问如何在T时间内能到达n点并且获得的能量值尽量多
解题思路:先dfs找出1到n的路径(肯定唯一),凡是在这条路上的边到必走且只要走一遍,其他的边要走的话,那么都要走两次(终点始终是n)我们把dfs出来的
路径全部置零,T-=该路径权值和。然后dp[u][j]表示以u为节点的子树在j时间内可获得的能量值,用背包就可以解决了,不过边的权值都要*2后计算,
并且子节点到达的前提是父亲节点已经到达。因此状态转移方程为:
dp[u][j]=max(dp[u][j],dp[u][j-2*w-k]+dp[v][k]);(j:w*2~T)(k:0~j-2*w)w为边权值
*/
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;
const int maxn=105;
struct note
{
int v,w,next;
}edge[maxn*2];
int head[maxn],ip;
int m,n,sum,dp[maxn][550],a[maxn];
void init()
{
memset(head,-1,sizeof(head));
ip=0;
}
void addedge(int u,int v,int w)
{
edge[ip].v=v,edge[ip].w=w,edge[ip].next=head[u],head[u]=ip++;
}
bool dfs(int u,int pre)///找出1~n的路径
{
if(u==n)return true;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(v==pre)continue;
if(dfs(v,u))
{
sum+=edge[i].w;
edge[i].w=0;
return true;
}
}
return false;///这句话必须有,因为这一句我没写WA到死.....
}
void get(int u,int pre)///输出该树
{
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(v==pre)continue;
printf("%d->%d:%d\n",u,v,edge[i].w);
get(v,u);
}
}
void dfs1(int u,int pre)
{
for(int i=0;i<=m;i++)
dp[u][i]=a[u];
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
int w=edge[i].w;
if(v==pre)continue;
dfs1(v,u);
for(int j=m;j>=2*w;j--)
{
for(int k=0;k+2*w<=j;k++)
{
dp[u][j]=max(dp[u][j],dp[u][j-2*w-k]+dp[v][k]);
}
}
}
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
init();
for(int i=0;i<n-1;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
addedge(u,v,w);
addedge(v,u,w);
}
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
sum=0;
dfs(1,-1);
/// get(1,-1);
m-=sum;
if(m<0)
{
printf("Human beings die in pursuit of wealth, and birds die in pursuit of food!\n");
continue;
}
/// printf("%d\n",sum);
memset(dp,0,sizeof(dp));
dfs1(1,-1);
printf("%d\n",dp[1][m]);
}
return 0;
}