ZOJ2111 HDU1011 Starship Troopers, 树形DP

60 篇文章 0 订阅
48 篇文章 0 订阅

经典的树形DP题, 题解请看代码中的注释


/*******************************************************************************
 # Author : Neo Fung
 # Email : neosfung@gmail.com
 # Last modified: 2012-02-03 18:04
 # Filename: ZOJ2111 HDU1011 Starship Troopers.cpp
 # Description : 树形DP. dp[x][y]表示的是在x点放置y人可以获得多少最多的brain.
 切记哪怕经过的点没有bug, 都需要放置人
 ******************************************************************************/
#ifdef _MSC_VER
#define DEBUG
#endif

#include <fstream>
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <string>
#include <limits.h>
#include <algorithm>
#include <math.h>
#include <numeric>
#include <functional>
#include <ctype.h>
#include <vector>
#define MAX 110
using namespace std;

vector<int> vec[MAX];
int bugs[MAX],brains[MAX];
bool visited[MAX];
int dp[MAX][MAX];

void init(const int &n)
{
	memset(visited,false,sizeof(visited));
	memset(dp,0,sizeof(dp));
	for(int i=0;i<=n;++i)
	{
		vec[i].clear();
	}
}

void add(const int &x,const int &y)
{
	vec[x].push_back(y);
	vec[y].push_back(x);
}

void dfs(const int &u, int m)
{
	visited[u]=true;
  int t=(bugs[u]+19)/20; 
  for(int i=t;i<=m;++i)
    dp[u][i]=brains[u];

	for(size_t i=0;i<vec[u].size();++i)
	{
		int v=vec[u][i];
		if(!visited[v])
		{
			dfs(v,m);

      // 假如到达节点 u 的有 j 人(j>=t),
      // 如果到达后继节点 v 的有k人, 则留在u的有j-k人
      // 则对于任一节点有dp[u][j]=max{dp[u][j-k]+dp[v][k]}; 
      for(int j=m;j>t;--j)
				for(int k=1;j-k>=t;++k)
						dp[u][j] = max(dp[u][j],dp[u][j-k]+dp[v][k]);
		}
	}
}

int main(void)
{
#ifdef DEBUG  
  freopen("../stdin.txt","r",stdin);
  freopen("../stdout.txt","w",stdout); 
#endif  

  int n,m,x,y;

  while(~scanf("%d%d",&n,&m)&& !(n==-1&&m==-1))
  {
	  init(n);
	  for(int i=1;i<=n;++i)
		  scanf("%d%d",&bugs[i],&brains[i]);
	  for(int i=1;i<n;++i)
	  {
		  scanf("%d%d",&x,&y);
		  add(x,y);
	  }
    if(m==0)
    {
      printf("0\n");
      continue;
    }
	  dfs(1,m);
	  printf("%d\n",dp[1][m]);
  }

  return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值