• HDU4276


    题目大意

    给定一棵n个结点的树,每个结点上有一定数量的treasure,经过每条边需要花一定的时间,要求你从结点1出发,在不超过时间T的情况下,最多能够获得的treasure是多少,并且要求结束于结点n

    题解

    本题主要的困难是如何恰好结束于结点n。

    先进行一次dfs求出从结点1到结点n的最短时间s(假设此条路径为a),如果s比T还大,不能走完,输出-1。否则的话继续处理,由于路径a是最短路径,因此肯定会经过此条路径,并且只会经过一次,其他的结点要么不经过,要么经过两次(因此时间花费是边权的两倍),接下来的任务就是在树上做背包了,但是如何使得最终结果一定会选取结点n呢?我们只需要把总时间减去最短时间s,并且把最短路径a上所有的边权全部赋为0,然后再进行动态规划,为什么这样做呢?因为我们选取最短路径上的结点不需要花时间,所以肯定会选啦!方程怎么表示呢?假设当前结点为u,某个子树为v,那么

    dp[u][j]=max(dp[u][j],dp[u][j-2*w-k]+dp[v][k] 表示从结点u开始花费j分钟能够获得的最大值,因为边(u,v)需要走两次,所以花费是2*w

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <iostream>
    using namespace std;
    #define MAXN 105
    vector<int>G[MAXN];
    int dp[MAXN][MAXN*5],value[MAXN],p[MAXN][MAXN];
    int n,T,V;
    bool dfs1(int rt,int u,int fa)
    {
        if(rt==u)
           return true;
        for(size_t i=0;i<G[u].size();i++)
        {
            int v=G[u][i];
            int w=p[u][v];
            if(fa==v) continue;
            if(dfs1(rt,v,u))
            {
                V+=w;
                p[u][v]=0;
                p[v][u]=0;
                return true;
            }
        }
        return false;
    }
    void dfs2(int u,int fa)
    {
         for(int i=0;i<=T;i++) dp[u][i]=value[u];
         for(size_t i=0;i<G[u].size();i++)
         {
             int v=G[u][i];
             int w=2*p[u][v];
            if(v==fa) continue;
            dfs2(v,u);
            for(int j=T;j>=w;j--)
            for(int k=0;k<=j-w;k++)
            dp[u][j]=max(dp[u][j],dp[u][j-k-w]+dp[v][k]); 
         }    
    }
    int main()
    {
        while(scanf("%d%d",&n,&T)!=EOF)
        {
             for(int i=0;i<MAXN;i++)
             {
                 G[i].clear();
             }
             for(int i=1;i<n;i++)
             {
                 int u,v,w;
                 scanf("%d%d%d",&u,&v,&w);
                 G[u].push_back(v);
                 G[v].push_back(u);
                 p[u][v]=p[v][u]=w;
             }
             for(int i=1;i<=n;i++) scanf("%d",&value[i]);
             memset(dp,0,sizeof(dp));
             V=0;
             dfs1(n,1,-1);
             if(V>T) 
                 printf("Human beings die in pursuit of wealth, and birds die in pursuit of food!
    ");
             else
             {
                  T-=V;
                  dfs2(1,-1);
                  printf("%d
    ",dp[1][T]);
             }
        }
        return 0;
    }
  • 相关阅读:
    Global Citizenship
    Eng Stu
    说说
    C#编程远程控制机械手臂
    切割系统
    C#编码 画图控件
    编程Sourceforge
    C#编程线程
    空间点的几何关系
    一台普通电脑通过设置连接到公司网络
  • 原文地址:https://www.cnblogs.com/zjbztianya/p/3434734.html
Copyright © 2020-2023  润新知