hdu1011Starship Troopers 树形DP

hdu1011


有很多细节需要理解

http://tobyaa.blog.163.com/blog/static/3024859120128260453244/

一棵树,有n个结点,每个结点有v个bug,有w的brain。我从1号结点开始走,带着m个战士。

1个战士可以消灭20个bugs,如果我把某个结点的所有bug都消灭了我就能得到那个结点的brain。
如果想攻击当前结点,那么必须先攻击了它的父结点(1号点除外)。
其中当你攻占了当前结点,你可以分派人手,走向几个不同的子结点,去攻占更多。也就是说,不是单一的路径。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;

int N,M,W[110],V[110];
vector<int>son[110];
int visit[110],dp[110][110];

void dfs(int n,int m){
	int len=son[n].size();
	visit[n]=1;
	if(m<W[n])	return;	
	dp[n][W[n]]=V[n];							//!! 
	
	for(int i=0;i<len;i++){
		if(visit[son[n][i]])	continue;
		dfs(son[n][i],m-W[n]);
		for(int j=m;j>=W[n];j--)
			for(int k=0;k<=j-W[n];k++)		//!! 
				if(dp[n][j]<dp[n][j-k]+dp[son[n][i]][k])
					dp[n][j]=dp[n][j-k]+dp[son[n][i]][k];
	}
	if(dp[n][0]>0){								//!! 
		dp[n][1] = max(dp[n][1],dp[n][0]);
		dp[n][0] = 0;
	}
}

int main()
{
	int i,j,k,u,v;
	
	while(scanf("%d%d",&N,&M),M!=-1&&N!=-1)
	{
		memset(dp,0,sizeof(dp));
		memset(visit,0,sizeof(visit));
		for(i=1;i<=N;i++)	son[i].clear();
		
		for(i=1;i<=N;i++){
			scanf("%d%d",&W[i],&V[i]);
			W[i]=(W[i]+19)/20;
		}
		for(i=1;i<=N-1;i++){
			scanf("%d%d",&u,&v);
			son[u].push_back(v);
			son[v].push_back(u);					//!! 
		}
		dfs(1,M);
		if(M==0)	printf("0\n");
		else	printf("%d\n",dp[1][M]);
		
	}
	return 0;
}


你可能感兴趣的:(hdu1011Starship Troopers 树形DP)