HDU 4276:The Ghost Blows Light 树形DP(2012 ACM/ICPC Asia Regional Changchun Online )

The Ghost Blows Light

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=4276

题意:

胡八一(男主角)被关在一个树形的墓地的根节点1上,现在他有T分钟逃离墓地,墓地的出口在N点,每条边都有权值wi(即经过这条边需要花费wi分钟),每个节点上都有宝藏,求在成功逃离墓地的前提下能获得的最多的宝物。

题解:

因为终点只有一个点N,所以可以视为其他所有的节点跑完后都需要折返回N点。将点1到点N的路径上的权值以及宝藏全都清零,更新答案以及T值(因为这条路径是必跑的)。

那么问题就简化为了在上一步的基础上,所有的节点在跑完后都需要折返回1,再从1跑到点N(花费为0),跑一遍树形DP就可以得到答案了。

      

代码

 

#include<stdio.h>
#include<string.h>
const int N=101;
const int M=501;
const int L=N*2;
struct edge
{
  int v,w,next;
}E[L*2];
int head[N],cnt,res,m,value[N],dp[N][M];
int mmax(int x,int y)
{
  return x>y?x:y;
}
bool mark[N];
void clean(int n)
{
  cnt=res=0;
  for(int i=1;i<=n;++i)
    head[i]=-1;
}
void add(int u,int v,int w)
{
  E[cnt].v=v;
  E[cnt].w=w;
  E[cnt].next=head[u];
  head[u]=cnt++;
}
bool Dfs_Findpath(int id,int n,int time)
{
  if(time<0)return false;
  mark[id]=true;
  for(int i=head[id];i!=-1;i=E[i].next)
  {
    int v=E[i].v;
    if(mark[v])continue;
    if(v==n||Dfs_Findpath(v,n,time-E[i].w))
    {
      if(v==n)
      {
        m=time-E[i].w;
        if(m<0)return false;
      }
      E[i].w=0;
      res+=value[v];
      value[v]=0;
      return true;
    }
  }
  return false;
}
void Dfs_TreeDp(int id)
{
  mark[id]=true;
  for(int i=head[id];i!=-1;i=E[i].next)
  {
    int v=E[i].v;
    int w=E[i].w;
    if(mark[v])continue;
    Dfs_TreeDp(v);
    for(int j=m;j>=0;--j)
    {
      for(int k=0;k<=j&&j-k-w*2>=0;++k)
        dp[id][j]=mmax(dp[id][j],dp[id][j-k-w*2]+dp[v][k]+value[v]);
    }
  }
}
void solve()
{
  int n,a,b,c;
  while(~scanf("%d%d",&n,&m))
  {
    clean(n);
    for(int i=1;i<n;++i)
    {
      scanf("%d%d%d",&a,&b,&c);
      add(a,b,c);
      add(b,a,c);
    }
    for(int i=1;i<=n;++i)
      scanf("%d",&value[i]);
    if(n==1)
    {
      printf("%d ",value[1]);
      continue;
    }
    memset(mark,false,sizeof(mark));
    if(!Dfs_Findpath(1,n,m))printf("Human beings die in pursuit of wealth, and birds die in pursuit of food! ");
    else
    {
      memset(mark,false,sizeof(mark));
      memset(dp,0,sizeof(dp));
      Dfs_TreeDp(1);
      printf("%d ",res+dp[1][m]+value[1]);
    }
  }
}
int main()
{
  solve();
  return 0;
}

  

原文地址:https://www.cnblogs.com/kiuhghcsc/p/5705732.html