您的位置:首页 > 其它

HDU 1561 The more, The Better

2013-06-28 21:27 274 查看
和上一篇一样,都是最近写的比较简单的树状背包。

这里我将0作为了根节点,并且m++,目的是方便处理,由于只有经过了根节点才能获得下面的宝藏,所以在每一层都令dp[rt][1] = val[rt];

以dp[rt][j]记录以rt为根攻打j个城堡所获得的最大宝物个数,则dp[rt][j] = max(dp[tree[rt][i]][k]+dp[rt][j-k],dp[rt][j]);tree[rt][i]为rt的儿子节点,即:想要在以rt为根节点的树上攻打j个城堡获得最大宝物数,就是在以rt的儿子为根节点的树上攻打k个城堡获得最大宝物数+在以rt为根节点的树上攻打j-k个城堡获得最大宝物数的和的最大值。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <algorithm>
#include <map>
#include <vector>
#include <stack>
using namespace std;
#define M 205
#define ll unsigned long long
#define int64 __int64
#define inf 1<<30

int n , m , val[M] , dp[M][M];
vector<int> tree[M];

void Dfs(int rt)
{
dp[rt][1] = val[rt];
int i , j , k , up = tree[rt].size();
for (i = 0 ; i < up ; i++)Dfs(tree[rt][i]);
for (i = 0 ; i < up ; i++)
{
for (j = m ; j > 1 ; j--)
{
for (k = 1 ; k < j ; k++)
{
dp[rt][j] = max(dp[tree[rt][i]][k]+dp[rt][j-k],dp[rt][j]);
}
}
}
}

int main()
{
int i , j;
while (scanf("%d%d",&n,&m) , m+n)
{
val[0] = 0;
for (i = 1 ; i <= n ; i++)
{
int a;
scanf("%d%d",&a,val+i);
tree[a].push_back(i);
}
m++;
memset(dp , -1 , sizeof dp);
Dfs(0);
printf("%d\n",dp[0][m]);
for (i = 0 ; i <= n ; i++)tree[i].clear();
}
return 0;
}


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: