现在的位置: 首页 > 综合 > 正文

HDU1561 The more,The better

2012年11月13日 ⁄ 综合 ⁄ 共 933字 ⁄ 字号 评论关闭

树形DP+分组背包

题意:从n座城堡中选m座城堡使财宝总量尽量大。有的城堡需要先攻克其他特定的一座城堡

思路:明显的树形结构,增加一个虚拟的0节点就是一棵树。设状态dp[i][j]为在以i为根的子树上选择j个节点的财富最大值;在非0节点上的其他点都必须选择他自己,所以非0节点从1开始记数。

华丽丽的被卡了一天,即使到现在重写第3次AC了还是不知道为什么错。头疼啊头疼

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

const int MAXN = 222;
int head[MAXN];
struct E{
	int v,next;
}edge[222];
int tot;
int dp[MAXN][MAXN];
int n,m;

int max(int a, int b) { return a>b?a:b; }

void add(int a, int b)
{
	edge[tot].next = head[a];
	edge[tot].v = b;
	head[a] = tot ++;
}

void gao(int cur)
{
	if(head[cur] == -1) return ;
	int p;
	int i,j;
	for(p=head[cur]; p!=-1; p=edge[p].next)
	{
		gao(edge[p].v);
		for(i=m; i>=0; i--)
		{
			if(dp[cur][i] < 0) continue;
			for(j=0; i+j<=m; j++)
			{
				if(dp[edge[p].v][j] < 0) continue;
				dp[cur][i+j] = max(dp[cur][i+j], dp[cur][i]+dp[edge[p].v][j]);
			}
		}
	}
}

int main()
{
	int i,a,b;
	while(scanf("%d%d", &n, &m),n||m)
	{
		tot = 0;
		memset(head, -1, sizeof(head));
		memset(dp, -1, sizeof(dp));
		for(i=1; i<=n; i++)
		{
			scanf("%d%d", &a, &b);
			add(a,i);
			dp[i][1] = b;
		}
		dp[0][0] = 0;
		gao(0);
		printf("%d\n", dp[0][m]);
	}
	return 0;
}

抱歉!评论已关闭.