HDU 4276

题意:你在一座古墓里盗墓,古墓在T分钟时就会倒塌,你就挂了。古墓有n个房间,每个房间都有一定价值的宝藏,n-1条边,每条边有花费的时间,形成一棵树。如果逃不出去就输出Human beings die in pursuit of wealth, and birds die in pursuit of food!  如果能逃出去,那么输出能获得的最大价值是多少。

思路:先dfs算出到n点的最短路,然后判断时间是否大于T。如果大于T就输出Human beings die in pursuit of wealth, and birds die in pursuit of food!   如果能逃出去,那么起点到终点上的点是必须走的,所以把起点到终点上的边的花费设为0,然后把剩余的时间T减去最短路花费的时间。接下来的问题就是剩余时间T能获得的最大价值。就是一个树形DP,参考了一下网上的博客。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <vector>
#include <cmath>
using namespace std;
const int INF=0x3f3f3f3f;
const int MAXN=110;
const int MAXT=550;
struct Edge{
    int u,v,w,nex;
}edge[MAXN*2];
int tot,u,v,w;
int val[MAXN];
int pre[MAXN];
int head[MAXN];
int dist[MAXN];
vector<int> lu;
int dp[MAXN][MAXT];
int n,ti;

void addedge(int u,int v,int w)
{
    edge[tot].u=u;
    edge[tot].v=v;
    edge[tot].w=w;
    edge[tot].nex=head[u];
    head[u]=tot++;
}

void dfs(int u,int pr)
{
    for(int i=head[u];i!=-1;i=edge[i].nex)
    {
        Edge e=edge[i];
        if(e.v==pr)
            continue;
        pre[e.v]=i;
        dist[e.v]=dist[u]+e.w;
        dfs(e.v,u);
    }
}

void dfs2(int u,int pre)
{
    for(int i=0;i<=ti;i++)
        dp[u][i]=val[u];

    for(int i=head[u];i!=-1;i=edge[i].nex)
    {
        Edge e=edge[i];
        if(e.v==pre)
            continue;
        dfs2(e.v,u);
        for(int j=ti;j>=2*e.w;j--)
            for(int k=0;k<=j-2*e.w;k++)
                dp[u][j]=max(dp[u][j],dp[u][j-k-2*e.w]+dp[e.v][k]);
    }
}

void init()
{
    tot=0;
    memset(head,-1,sizeof(head));
    memset(pre,-1,sizeof(pre));
    for(int i=0;i<MAXN;i++)
        dist[i]=INF;
}
int main()
{
    freopen("in.txt","r",stdin);
    while(scanf("%d%d",&n,&ti)!=EOF)
    {
        init();
        for(int i=0;i<n-1;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            addedge(u,v,w);
            addedge(v,u,w);
        }
        for(int i=1;i<=n;i++)
            scanf("%d",&val[i]);
        dist[1]=0;
        dfs(1,-1);

        if(dist[n]>ti)
        {
            puts("Human beings die in pursuit of wealth, and birds die in pursuit of food!");
            continue;
        }
        for(int i=n;i!=1;i=edge[pre[i]].u)
            edge[pre[i]].w=edge[pre[i]^1].w=0;

        ti-=dist[n];
        dfs2(1,-1);

        printf("%d\n",dp[1][ti]);
    }
    return 0;
}

时间: 2024-08-10 02:01:52

HDU 4276的相关文章

hdu 4276(树形dp)

题意:带权树上有起点终点每个点上有宝藏,一个人只有T分钟要从起点到重点,问你最多能收集多少宝藏. 思路:树形dp,首先判断能不能走到终点,然后把路径上的边权变为0时间减去所有边权.dp[v][j]表示从v出发回到v话费j分钟最多能收集到的宝藏. dp[v][j] = max(dp[v][j], dp[x][k] + dp[v][j-k-2*val]); 被G++卡了好长时间,换成c++就过了. 代码如下: 1 #include <stdio.h> 2 #include <string.h

hdu 4276 The Ghost Blows Light(DP-树形DP)

The Ghost Blows Light Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2240    Accepted Submission(s): 688 Problem Description My name is Hu Bayi, robing an ancient tomb in Tibet. The tomb consi

HDU 4276 - The Ghost Blows Light

The Ghost Blows Light Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3345    Accepted Submission(s): 1040 Problem Description My name is Hu Bayi, robing an ancient tomb in Tibet. The tomb consi

HDU 4276 The Ghost Blows Light (树形DP,变形)

题意:给定一棵n个节点的树,起点是1,终点是n,每经过一条边需要消耗Ti天,每个点上有一定量的珠宝,要求必须在t天内到达终点才可以将珠宝带出去,问至多能带多少珠宝? 思路: 注意Ti可以为0,而且有可能t太小以至于不能到达n,则输出不可达.这样想会简单点,将"1->n"路径上的每条边断开,变成一片森林,而且路径上的这些点是根.我们需要计算每棵树在j天内最多能获得多少珠宝,这只需要一次DFS就可以完成了.然后除了森林中的根(即1->n路径上的点),其他都可以不用考虑了,按照&

HDU 4276 The Ghost Blows Light(树形)

题意:给出一棵n个节点的树,起点1,终点n,相连的两个节点之间有距离,每个节点有个价值,给出一个时间T.问从1到达n在给定时间T内取得的最大价值? 思路:先从1走到n,如果总的时间不够走完,直接退出,否则把时间扣掉,这些边权设置为0,然后做一遍树形DP 1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream>

DP题目

//HDU 4001 To Miss Our Children Time HDU 4433 locker HDU 4362 Dragon Ball[] HDU 3602 2012[] HDU 4385 Moving Bricks[] HLG 1067 QQ Farm[] HDU 4293 Groups HDU 3920 Clear All of Them I[] HDU 3466 Proud Merchants[] POJ 2923 Relocation[] HDU 3660 Alice and

HDU 4287 Intelligent IME(map运用)

转载请注明出处:http://blog.csdn.net/u012860063 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4287 Intelligent IME Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2091    Accepted Submission(s): 1031

HDU 6203 ping ping ping [LCA,贪心,DFS序,BIT(树状数组)]

题目链接:[http://acm.hdu.edu.cn/showproblem.php?pid=6203] 题意 :给出一棵树,如果(a,b)路径上有坏点,那么(a,b)之间不联通,给出一些不联通的点对,然后判断最少有多少个坏点. 题解 :求每个点对的LCA,然后根据LCA的深度排序.从LCA最深的点对开始,如果a或者b点已经有点被标记了,那么continue,否者标记(a,b)LCA的子树每个顶点加1. #include<Bits/stdc++.h> using namespace std;

HDU 5542 The Battle of Chibi dp+树状数组

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5542 题意:给你n个数,求其中上升子序列长度为m的个数 可以考虑用dp[i][j]表示以a[i]结尾的长度为j的上升子序列有多少 裸的dp是o(n2m) 所以需要优化 我们可以发现dp的第3维是找比它小的数,那么就可以用树状数组来找 这样就可以降低复杂度 #include<iostream> #include<cstdio> #include<cstring> #include