HDU 4276 The Ghost Blows Light
把1~N的路径处理出来,算出需要的时间,如果时间不够就直接挂了,时间多的话就可以去用这些时间去拿别的物品了。
对1~N这条路径上的所有点做一遍树形背包,注意背包时不要背到这条路径上的点,否则就重复计算了。最后再将路径上的点用背包合并即可。
代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <memory.h>
#include <algorithm>
using namespace std;
const int N=110;
const int E=N<<1;
const int MAXT=510;
int v[N],mark[N];
int dp[N][MAXT];
int n,t;
struct Edge{
int to;
int time;
int next;
int cost() const {
return mark[to]?0:time*2;
}
};
int head[N],cnt;
Edge edge[E];
void addedge(int s,int e,int time){
++cnt;
edge[cnt].to=e;
edge[cnt].time=time;
edge[cnt].next=head[s];
head[s]=cnt;
}
int dfs_edge(int x,int from=-1) {
if(x==n) {
return 0;
}
for(int i=head[x];i;i=edge[i].next) if(edge[i].to!=from) {
int val;
if((val=dfs_edge(edge[i].to,x))!=-1) {
mark[edge[i].to]=1;
return val+edge[i].time;
}
}
return -1;
}
void dfs_dp(int x,int C,int from=-1) {
if(C<=0) return;
if(from==-1) {
for(int i=0;i<=C;i++) dp[x][i]=v[x];
}
for(int i=head[x];i;i=edge[i].next) if(edge[i].to!=from) {
int son=edge[i].to;
int cost=edge[i].cost();
for(int i=0;i<=C-cost;i++) dp[son][i]=dp[x][i]+v[son];
dfs_dp(son,C-cost,x);
for(int k=cost;k<=C;k++) {
dp[x][k]=max(dp[x][k],dp[son][k-cost]);
}
}
}
void print() {
for(int i=1;i<=n;i++) {
for(int j=0;j<=t;j++) printf(" %d",dp[i][j]);
putchar('\n');
}
}
int main() {
while(scanf("%d%d",&n,&t)!=EOF) {
memset(head,0,sizeof(head));
cnt=0;
for(int i=0;i<n-1;i++) {
int s,e,time;
scanf("%d%d%d",&s,&e,&time);
addedge(s,e,time);
addedge(e,s,time);
}
for(int i=1;i<=n;i++) scanf("%d",&v[i]);
memset(dp,0xbf,sizeof(dp));
memset(mark,0,sizeof(mark));
mark[1]=mark[n]=1;
int dec=dfs_edge(1);
dfs_dp(n,t-dec);
int ans=-1;
for(int i=0;i<=t;i++) ans=max(ans,dp[n][i]);
if(ans==-1) printf("Human beings die in pursuit of wealth, and birds die in pursuit of food!\n");
else printf("%d\n",ans);
}
return 0;
}