HDU 4276 The Ghost Blows Light [树形背包DP]

  把1~N的路径处理出来,算出需要的时间,如果时间不够就直接挂了,时间多的话就可以去用这些时间去拿别的物品了。

  对1~N这条路径上的所有点做一遍树形背包,注意背包时不要背到这条路径上的点,否则就重复计算了。最后再将路径上的点用背包合并即可。

  不过我这么写效率好像比较慢,跑了150ms+ ,rank上有不少0ms的,应该是有更好的算法。。

  

 1 #include <stdio.h>
 2 #include <string.h>
 3 #define MAXN 105
 4 struct edge{
 5     int v,w,n;
 6 }e[MAXN*2];
 7 int first[MAXN],es;
 8 int n,t,tu,tv,tw;
 9 void addedge(int u,int v,int w){
10     e[es].w=w,e[es].v=v,e[es].n=first[u],first[u]=es++;
11 }
12 int fa[MAXN],vis[MAXN],col[MAXN];
13 int map[MAXN][MAXN],val[MAXN];
14 void dfsfa(int u,int f){
15     for(int i=first[u];i!=-1;i=e[i].n){
16         int v=e[i].v;
17         if(v==f)continue;
18         fa[v]=u;
19         dfsfa(v,u);
20     }
21 }
22 //第i点时间t最多能拿到的宝物
23 int d[105][505],d2[505],t2;
24 inline int max(const int &x,const int &y){return x>y?x:y;}
25 void dp(int u,int f){
26     for(int i=0;i<=t;i++)d[u][i]=val[u];
27     for(int i=first[u];i!=-1;i=e[i].n){
28         int v=e[i].v;
29         if(v==f||col[v]==1)continue;
30         dp(v,u);
31         int dd=2*e[i].w;
32         for(int i1=t;i1>=0;i1--){
33             for(int j1=0;j1+dd<=i1;j1++){
34                 d[u][i1]=max(d[u][i1],d[u][j1]+d[v][i1-j1-dd]);
35             }
36         }
37     }
38 }
39 
40 int main(){
41     freopen("test.in","r",stdin);
42     while(scanf("%d%d",&n,&t)!=EOF){
43         memset(first,-1,sizeof first);es=0;
44         for(int i=1;i<n;i++){
45             scanf("%d%d%d",&tu,&tv,&tw);
46             addedge(tu,tv,tw);
47             addedge(tv,tu,tw);
48             map[tu][tv]=map[tv][tu]=tw;
49         }
50         for(int i=1;i<=n;i++)scanf("%d",&val[i]);
51         memset(col,0,sizeof col);
52         dfsfa(1,-1);
53         col[1]=1,fa[1]=-1;
54         int dis=0,disv=val[1];
55         for(int i=n;i!=1;i=fa[i]){
56             col[i]=1;
57             dis+=map[i][fa[i]];
58             disv+=val[i];
59         }
60         if(dis>t){
61             printf("Human beings die in pursuit of wealth, and birds die in pursuit of food!\n");
62             continue;
63         }
64         t=t-dis;
65         memset(d2,0,sizeof d2);
66         for(int i=1;i<=n;i++){
67             if(col[i]==0)continue;
68             dp(i,fa[i]);
69             for(int i1=t;i1>=0;i1--){
70                 for(int j1=0;j1<=i1;j1++){
71                     d2[i1]=max(d2[i1],d2[j1]+d[i][i1-j1]-val[i]);
72                 }
73             }
74         }
75         for(int i=0;i<t;i++)d2[t]=max(d2[t],d2[i]);
76         printf("%d\n",d2[t]+disv);
77     }
78     return 0;
79 }
posted @ 2012-09-10 23:04  Burn_E  阅读(200)  评论(0)    收藏  举报