zoukankan      html  css  js  c++  java
  • hdu 3660 Alice and Bob's Trip(树形DP)

    Alice and Bob's Trip

    Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 2643    Accepted Submission(s): 708

    Problem Description
    Alice and Bob are going on a trip. Alice is a lazy girl who wants to minimize the total travelling distance, while Bob as an active boy wants to maximize it. At the same time, they cannot let the value to be less than a given integer L since that will make them miss too much pleasure, and they cannot let the value to be greater than a given integer R since they don't want to get too exhausted.
    The city they are visiting has n spots and the spots are connected by directed edges. The spots are connected in such a way that they form a tree and the root will always be at spot 0. They take turns to select which edge to go. Both of them choose optimally. Bob will go first.
     
    Input
    There are multiple test cases. For every test case, the first line has three integers, n, L and R (1<=n<=500000, 0<=L, R<=1000000000). The next n-1 lines each has three integers a, b and c, indicating that there is an edge going from spot a to spot b with length c (1<=c<=1000). The spots are labeled from 0 to n-1.
    There is a blank line after each test case.
    Proceed to the end of file.
     
    Output
    If the total distance is not within the range [L, R], print "Oh, my god!" on a single line. Otherwise, print the most value Bob can get.
     
    Sample Input
    3 2 4 0 1 1 0 2 5 7 2 8 0 1 1 0 2 1 1 3 1 1 4 10 2 5 1 2 6 5 7 4 8 0 1 1 0 2 1 1 3 1 1 4 2 2 5 1 2 6 5 4 2 6 0 1 1 1 2 1 1 3 5
     
    Sample Output
    Oh, my god! 2 6 2
     
    Source
     
    Recommend
    lcy   |   We have carefully selected several similar problems for you:   3669  3668  3667  3666  3662 
     

    题意:

    A和B要去旅游。这有N个城市。而这些的城市的道路为一颗树。且边有向。A和B从0出发一起去旅游。A很懒想尽量少走路。B很有活力想尽量多走路但是无论怎么选择他们走的总路程都必须满足在[L,R]的范围内。所以他们交替选择走哪条路。开始由B选。然后问你在都采用最优策略的情况下。B最多能走多少路。

    思路:

    算是比较水的树形DP吧。由于道路是一颗树所以很多东西是可以确定的。比如根到这个节点的距离。和该结点由谁选择。所以就很简单了。用dp[i]表示经过i号结点B所能获得的最大价值。为-1时表示不能经过该结点。比赛时太困了大脑完全就不转了。还好队友解决了。下来一下下就解决了。不过比赛时要优化输入才过不然要TLE。在外面用C++交就不会超时了。

    详细见代码:

    #include<algorithm>
    #include<iostream>
    #include<string.h>
    #include<sstream>
    #include<stdio.h>
    #include<math.h>
    #include<vector>
    #include<string>
    #include<queue>
    #include<set>
    #include<map>
    using namespace std;
    const int INF=0x3f3f3f3f;
    const int maxn=500010;
    int cnt,n,L,R;
    int dp[maxn];
    struct node
    {
        int v;
        int val;
        node *next;
    } edge[maxn],*head[maxn];
    void adde(int u,int v,int w)
    {
        edge[cnt].v=v;
        edge[cnt].val=w;
        edge[cnt].next=head[u];
        head[u]=&edge[cnt++];
    }
    void dfs(int np,int d,bool ok)//ok=1表示B选0表示A选
    {
        node *p;
        if(head[np]==NULL)//到叶子结点时判断可行性。
        {
            if(d>=L&&d<=R)
                dp[np]=d;
            else
                dp[np]=-1;
            return ;
        }
        for(p=head[np];p!=NULL;p=p->next)//只有先处理完儿子才能确定自己
            dfs(p->v,d+p->val,ok^1);
        if(ok)//初始化
            dp[np]=-1;
        else
            dp[np]=INF;
        for(p=head[np];p!=NULL;p=p->next)
        {
            if(ok)
                dp[np]=max(dp[np],dp[p->v]);
            else if(dp[p->v]!=-1)
                dp[np]=min(dp[np],dp[p->v]);
        }
        if(dp[np]==INF)
            dp[np]=-1;
        //printf("np %d  %d
    ",np,dp[np]);
    }
    inline int getint()//优化输入
    {
        char ch=getchar();
        int ans= 0;
        while(ch<'0'||ch>'9')
            ch=getchar();
        do
        {
            ans=ans*10+ch-'0';
            ch=getchar();
        }while(ch>='0'&&ch<='9');
        return ans;
    }
    int main()
    {
        int i,u,v,w;
    
        while(~scanf("%d%d%d",&n,&L,&R))
        {
            cnt=0;
            memset(head,0,sizeof head);
            for(i=1;i<n;i++)
            {
                //scanf("%d%d%d",&u,&v,&w);//优化前1765ms。优化后781ms。所以大型输入时最好还是优化下
                u=getint();
                v=getint();
                w=getint();
                adde(u,v,w);
            }
            dfs(0,0,1);
            if(dp[0]>=0)
                printf("%d
    ",dp[0]);
            else
                printf("Oh, my god!
    ");
        }
        return 0;
    }
    


  • 相关阅读:
    AtCoder Beginner Contest 064 D
    ZOJ 3956 Course Selection System [01背包]
    理解01背包
    模块(二)
    内置函数+递归+模块使用
    函数进阶
    使用markdown编辑器
    函数进阶(二)
    函数进阶(一)
    函数基础
  • 原文地址:https://www.cnblogs.com/pangblog/p/3402486.html
Copyright © 2011-2022 走看看