hdu 4276 The Ghost Blows Light 树形dp 时间优化技巧

来源:互联网 发布:c语言,a 什么意思 编辑:程序博客网 时间:2024/06/10 01:39


The Ghost Blows Light

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3240    Accepted Submission(s): 1000


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)
 

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 101 2 2 2 3 22 5 33 4 31 2 3 4 5
 

Sample Output
11
 

Source
2012 ACM/ICPC Asia Regional Changchun Online
 

Recommend
liuyiding
 

Statistic | Submit | Discuss | Note

题意:

有n个房间构成一棵树结构,n-1条路都有权值,代表经过花费的时间,一个人在房间1,出口在房间n,T秒后这座房子将要倒塌。每个房间有一定价值的宝物,问逃出时最大可带走多少价值的宝物。如果无法逃出特别输出。

(超过T秒没有到达房间n算作未逃出)


之前有个想法:dp[x][v][0] dp[x][v][1]表示从x出发经过k步回到x点的最大收益和不回到x点的最大收益。

按理来说这种做法是可行的,结果这样不断T。


解法:先找到1到n的必经之路,这些边只会走一次,而其它边会走两次。

如果这些边的权值和sumW>T,证明无法逃出,continue。

否则,用T减去权值和sumW,并将这些边的权值赋为0。


之后进行树形背包,这样可以保证走过这些必经之边。





#include<cstdio>#include<string>#include<cstring>#include<iostream>#include<cmath>#include<algorithm>#include<vector>using namespace std;#define all(x) (x).begin(), (x).end()#define for0(a, n) for (int (a) = 0; (a) < (n); (a)++)#define for1(a, n) for (int (a) = 1; (a) <= (n); (a)++)#define mes(a,x,s)  memset(a,x,(s)*sizeof a[0])#define mem(a,x)  memset(a,x,sizeof a)typedef long long ll;typedef pair<int, int> pii;const int INF =0x3f3f3f3f;const int maxn= 100    ;const int maxT= 500    ;int n,nedge,T,a[maxn+10];int fir[maxn+10],nex[2*maxn+10],to[2*maxn+10],W[2*maxn+10];int dp[maxn+5][maxT+5];inline void add_edge(int x,int y,int w){    to[nedge]=y;    W[nedge]=w;    nex[nedge]=fir[x];    fir[x]=nedge++;}void update(int &x,int val){    if(val>x)   x=val;}void dfs(int x,int fa){    for0(v,T+1)    {        dp[x][v]=a[x];    }    for(int i=fir[x];~i;i=nex[i])    {        int y=to[i];if(y==fa)  continue;        int w=W[i];        dfs(y,x);        for(int v=T;v>=2*w;v--)        {            int ret=dp[x][v];            for(int v2=0;v2+2*w<=v;v2++)            {                 update(ret,dp[y][v2]+dp[x][v-v2-2*w]);            }            dp[x][v]=ret;        }    }}int time;bool pre(int x,int fa){    if(x==n)    {        return true;    }    bool ok=false;    for(int i=fir[x];~i ;i=nex[i])    {        int y=to[i];if(y==fa) continue;        int & w=W[i];        if(pre(y,x))        {             ok=true;             time+=w;             w=0;        }    }    return ok;}int main(){   std::ios::sync_with_stdio(false);   while(cin>>n>>T)   {       int x,y,w;       nedge=0;       mes(fir,-1,(n+1));       for1(i,n-1)       {           cin>>x>>y>>w;           add_edge(x,y,w);           add_edge(y,x,w);       }       for1(i,n)  cin>>a[i];       time=0;       pre(1,-1);       if(time>T)   {puts("Human beings die in pursuit of wealth, and birds die in pursuit of food!");continue;}       T-=time;       dfs(1,-1);       printf("%d\n",dp[1][T]);   }   return 0;}/*2 51 2 51 2ans=32 41 2 51 2ans =no1 55ans=5*/


0 0