hdu 1011 Starship Troopers_树状dp

题目链接

题意:给你一棵树(必须从根节点出发),每个节点上都有bug和value,你有m个骑士,每个骑士能消灭20个bug,你必须消灭该节点的全部bug才能拿到该节点的value,问最多能拿到value是多少.

思路:典型的背包dp ,  dp[n][m]=max(dp[n][m-x]+value,dp[n][m])


#include<iostream>
#include<cstdio>
using namespace std;
#define N 110
#define INF 999999999
struct node
{
	int v,next;
}edge[N<<1];
int adj[N],vis[N],room[N][2],dp[N][N],edgeNum;
int max(int a,int b){return a>b?a:b;}
void AddEdge(int u,int v)
{
	edge[edgeNum].v=v,edge[edgeNum].next=adj[u],adj[u]=edgeNum++;
	edge[edgeNum].v=u,edge[edgeNum].next=adj[v],adj[v]=edgeNum++;
}
void init()
{
	memset(vis,0,sizeof(vis));
	memset(adj,-1,sizeof(adj));
	memset(dp,0,sizeof(dp));
	edgeNum=0;
}
void dfs(int u,int m)
{
	int num=room[u][0]/20,i,j,k;
	if(room[u][0]%20)//bug多于二十的倍数当然要多一个骑士消灭bug 
		num++;
	vis[u]=1;
	for(i=num;i<=m;i++)
		dp[u][i]=room[u][1];//加上该节点的价值 
	for(i=adj[u];i!=-1;i=edge[i].next)
	{
		int v=edge[i].v;
		if(!vis[v])
		{
			dfs(v,m);
			for(j=m;j>=num;j--)
			{
				for(k=1;j+k<=m;k++)
					if(dp[v][k])
						dp[u][k+j]=max(dp[u][k+j],dp[u][j]+dp[v][k]);//背包求最优价值 
			}
		}
	}


}
int main()
{
	int n,m;
	int i,u,v;
	while(scanf("%d%d",&n,&m))
	{
		if(n==-1&&m==-1)
			break;
		init();
		for(i=1;i<=n;i++)
			scanf("%d%d",&room[i][0],&room[i][1]);
		for(i=1;i<n;i++)
		{
			scanf("%d%d",&u,&v);
			AddEdge(u,v);//单向 
		}
		if(m==0)//没有骑士 
		{
			printf("0\n");
			continue;
		}
		dfs(1,m);//必须从节点1开始 
		printf("%d\n",dp[1][m]);

	}
	return 0;
}



posted @ 2014-04-13 11:26  Teemo的技术blog  阅读(133)  评论(0编辑  收藏  举报