HDU 4276 The Ghost Blows Light(树形DP)

本文介绍了一种使用树形DP(Dynamic Programming)的方法来解决无向树中从起点到终点的最大权值路径问题。在给定的时间限制内,通过预计算最短路径并将其时间置零,转化为树状结构的子问题进行递归求解,从而在复杂情况下高效地找到最优解。

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

题意:给出一棵无向树,从1走到n,总时间为T,每走一条边需要花费一定时间,每个结点有一定权值,问在指定时间内到达n点能获取的最大权值。


由于已经到过的点能再次返回(虽然不能再次获得该点权值),情况数倍增.....普通搜索必然爆

参考神方法:先用某种方法跑出1到n的最短路径,如果时间限定之内,继续,因为最短路上的边只会走一遍才是最优的,多走就是多余的,将最短路的边的时间变为0,总时间减去最短路时间。把最短路当做根,现在其他的路径就是分支了,分支有走两边或者不走两种情况.....就是树形DP了



#include <cstdio>
#include <cmath>
#include <iostream>
#include <cstring>
# define MAX 222
# define INF 0x7FFFFFFF
using namespace std;

struct node {
    int s,e,v,next;
} ed[MAX];
int head[MAX],num = 0,n,m,tim,flag,timee;
int dp[MAX][5555],va[MAX]; // dp[i][j] 表示回到i点时使用了j的时间能获得的最多的权值

void add(int s,int e,int v) {
    ed[num].s = s;
    ed[num].e = e;
    ed[num].v = v;
    ed[num].next = head[s];
    head[s] = num++;
}

void init() {
    memset(head,-1,sizeof(head));
    num = 0;
    flag = 0;
    timee = 0;
}

int dfstime(int v0,int pre) {
    if(v0 == n) return 1;
    for(int i=head[v0];i != -1; i =ed[i].next) {
        int e = ed[i].e ;
        if(e != pre) {
            if(dfstime(e,v0)) {
                timee += ed[i].v;
                ed[i].v = 0;
                return 1;
            }
        }
    }
    return 0;
}

void dfs(int v0,int pre) {
    for(int i=0; i<=tim; i++) dp[v0][i] = va[v0];
    for(int i=head[v0];i != -1; i = ed[i].next) {
        int e = ed[i].e ;
        if(e != pre) {
            dfs(e,v0);
            int cost = ed[i].v * 2;
            for(int j=tim; j>=cost; j--) {
                for(int k=0; k<=j -cost; k++) {
                    dp[v0][j] = max(dp[v0][j],dp[e][k] + dp[v0][j-k-cost]);
                }
            }
        }
    }
}

int main() {
    int i,a,b,c;
    while(cin >> n >> tim) {
        init();
        for(i=0; i<n-1; i++) {
            scanf("%d%d%d",&a,&b,&c);
            add(a,b,c);
            add(b,a,c);
        }
        for(i=1; i<=n; i++) {
            scanf("%d",&va[i]);
        }
        dfstime(1,-1);
        if(tim < timee) {
            printf("Human beings die in pursuit of wealth, and birds die in pursuit of food!\n");
            continue;
        }
        tim -= timee ;//最短路上的花费已经为0
        dfs(1,-1);
        printf("%d\n",dp[1][tim]);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值