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

来源:互联网 发布:雷欧奥特曼mac装备 编辑:程序博客网 时间:2024/06/15 10:55

题目地址: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 50500int 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;}


原创粉丝点击