HDU 4616 Game (搜索)、(树形dp)

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4616


这道题目数据可能比较弱,搜索都可以AC,但是不敢写,哎……


搜索AC代码:

 

#include <iostream>

#include <cstdio>

#include <cstring>

#include <string>

#include <cstdlib>

#include <cmath>

#include <vector>

#include <list>

#include <deque>

#include <queue>

#include <iterator>

#include <stack>

#include <map>

#include <set>

#include <algorithm>

#include <cctype>

#include <ctime>

#pragma comment(linker, "/STACK:16777216")

using namespace std;



typedef __int64 LL;

const int N=50005;

const int M=55555555;

const int INF=0x3f3f3f3f;

const double PI=acos(-1.0);



vector<int>q[N];

int xh[N],w[N];

int n,c,sm;

bool vis[N];



struct love

{

    int i,sum;

    int cc;

}r,e,my[M];



void BFS(int s)

{

    memset(vis,0,sizeof(vis));

    vis[s]=1;

    vector<int>::iterator it;

    r.i=s;

    r.sum=xh[s];    sm=max(sm,r.sum);

    r.cc=c-w[s];

    if(r.cc==0)

        return ;

    int he=0,ta=0;

    my[ta++]=r;

    while(he!=ta)

    {

        e=my[he++];

        if(he==M)

            he=0;

        for(it=q[e.i].begin();it!=q[e.i].end();it++)

        {

            r=e;

            int k=*it;

            if(vis[k])  continue;

            vis[k]=1;

            r.i=k;

            r.sum+=xh[k];   sm=max(sm,r.sum);

            r.cc-=w[k];

            if(r.cc>0)

            {

                my[ta++]=r;

                if(ta==M)

                    ta=0;

            }

        }

    }

}



int main()

{

    int T;

    scanf("%d",&T);

    while(T--)

    {

        scanf("%d%d",&n,&c);

        for(int i=0;i<n;i++)

        {

            scanf("%d%d",&xh[i],&w[i]);

        }

        for(int i=0;i<=n;i++)

            q[i].clear();

        for(int i=0;i<n-1;i++)

        {

            int a,b;

            scanf("%d%d",&a,&b);

            q[a].push_back(b);

            q[b].push_back(a);

        }

        int Max=-1;

        for(int i=0;i<n;i++)

        {

            sm=0;

            if(q[i].size()==1)

                BFS(i);

            if(Max<sm)

                Max=sm;

        }

        cout<<Max<<endl;

    }

    return 0;

}


 

树形DP代码:

 

#include <iostream>

#include <cstdio>

#include <vector>

#include <cstring>

using namespace std;

#define N 50500

int trap[N],val[N],n,C,vis[N],ans;

int dp[N][5][2];

vector<int>vec[N];



void DP(int u)

{

    vis[u]=1;

    dp[u][trap[u]][0]=dp[u][trap[u]][1]=val[u];

    int v;

    for(int i=0;i<vec[u].size();++i)

    {

        v=vec[u][i];

        if(vis[v]) continue;

        DP(v);

        for(int j=0;j<=C;++j)

            for(int k=0;j+k<=C;++k)

        {

            if(j!=C) // j=C的时候已经停止了,不会再往子节点跑了

                ans=max(ans,dp[u][j][0]+dp[v][k][1]);

            if(k!=C) // 同理

                ans=max(ans,dp[u][j][1]+dp[v][k][0]);

            if(j+k<C) // 0表示从子树方向往根节点跑,子树可能是非陷阱的点,

                //假如j+k==C,题意要求到达C要停止,但按dp[v][k][0]记录的,还会继续跑,所以不行

                ans=max(ans,dp[u][j][0]+dp[v][k][0]);

            //if(j+k<C)

                //ans=max(ans,dp[u][j][1]+dp[v][k][1]); 

        }

        for(int j=0;j+trap[u]<=C;++j)

            dp[u][j+trap[u]][0]=max(dp[u][j+trap[u]][0],dp[v][j][0]+val[u]);

        for(int j=1;j+trap[u]<=C;++j) // 1表示从根节点往下走的,1->0是不可取的,因为算上1后,已经满C了,就不会再走了,所以不能更新

            dp[u][j+trap[u]][1]=max(dp[u][j+trap[u]][1],dp[v][j][1]+val[u]);

    }

}

int main ()

{

    int ncase;scanf("%d",&ncase);

    while(ncase--)

    {

        scanf("%d%d",&n,&C);

        for(int i=0;i<n;++i)

            vec[i].clear();

        memset(vis,0,sizeof(vis));

        memset(dp,0,sizeof(dp));

        ans=0;

        for(int i=0;i<n;++i)

            scanf("%d%d",&val[i],&trap[i]);

        int u,v;

        for(int i=1;i<n;++i)

        {

            scanf("%d%d",&u,&v);

            vec[u].push_back(v);

            vec[v].push_back(u);

        }

        DP(0);

        printf("%d\n",ans);

    }

    return 0;

}


 

 

你可能感兴趣的:(game)