您的位置:首页 > 其它

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

2012-09-10 23:04 447 查看
  把1~N的路径处理出来,算出需要的时间,如果时间不够就直接挂了,时间多的话就可以去用这些时间去拿别的物品了。

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

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

  

#include <stdio.h>
#include <string.h>
#define MAXN 105
struct edge{
int v,w,n;
}e[MAXN*2];
int first[MAXN],es;
int n,t,tu,tv,tw;
void addedge(int u,int v,int w){
e[es].w=w,e[es].v=v,e[es].n=first[u],first[u]=es++;
}
int fa[MAXN],vis[MAXN],col[MAXN];
int map[MAXN][MAXN],val[MAXN];
void dfsfa(int u,int f){
for(int i=first[u];i!=-1;i=e[i].n){
int v=e[i].v;
if(v==f)continue;
fa[v]=u;
dfsfa(v,u);
}
}
//第i点时间t最多能拿到的宝物
int d[105][505],d2[505],t2;
inline int max(const int &x,const int &y){return x>y?x:y;}
void dp(int u,int f){
for(int i=0;i<=t;i++)d[u][i]=val[u];
for(int i=first[u];i!=-1;i=e[i].n){
int v=e[i].v;
if(v==f||col[v]==1)continue;
dp(v,u);
int dd=2*e[i].w;
for(int i1=t;i1>=0;i1--){
for(int j1=0;j1+dd<=i1;j1++){
d[u][i1]=max(d[u][i1],d[u][j1]+d[v][i1-j1-dd]);
}
}
}
}

int main(){
freopen("test.in","r",stdin);
while(scanf("%d%d",&n,&t)!=EOF){
memset(first,-1,sizeof first);es=0;
for(int i=1;i<n;i++){
scanf("%d%d%d",&tu,&tv,&tw);
addedge(tu,tv,tw);
addedge(tv,tu,tw);
map[tu][tv]=map[tv][tu]=tw;
}
for(int i=1;i<=n;i++)scanf("%d",&val[i]);
memset(col,0,sizeof col);
dfsfa(1,-1);
col[1]=1,fa[1]=-1;
int dis=0,disv=val[1];
for(int i=n;i!=1;i=fa[i]){
col[i]=1;
dis+=map[i][fa[i]];
disv+=val[i];
}
if(dis>t){
printf("Human beings die in pursuit of wealth, and birds die in pursuit of food!\n");
continue;
}
t=t-dis;
memset(d2,0,sizeof d2);
for(int i=1;i<=n;i++){
if(col[i]==0)continue;
dp(i,fa[i]);
for(int i1=t;i1>=0;i1--){
for(int j1=0;j1<=i1;j1++){
d2[i1]=max(d2[i1],d2[j1]+d[i][i1-j1]-val[i]);
}
}
}
for(int i=0;i<t;i++)d2[t]=max(d2[t],d2[i]);
printf("%d\n",d2[t]+disv);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: