把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 }