HDU 4276 The Ghost Blows Light

本文介绍了一种解决特定路径上背包问题的方法,利用DFS遍历树形结构,并结合树形背包思想,处理从根节点到目标节点路径上的资源收集问题。通过避免重复计算确保了算法的有效性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

转载于:https://www.cnblogs.com/programCaiCai/archive/2012/09/10/05838146e074ff404eb1df9144b350f5.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值