您的位置:首页 > 其它

HDU 1561 The more, The Better (树形dp)

2016-11-16 13:08 225 查看
是在树形结构上进行分组背包处理。本题的依赖关系可以理解成树边,到达子节点必须先经过父节点,本质是一样的,这样可以建立起一个森林,如果为每棵树的添加一个公共父节点0那就成了一棵树了,这是个实用性很强的小技巧。建立起一棵树就开始如何进行dp,如何从子节点获取信息。

    一个子节点就可以返回m个状态,每个状态表示容量为j(j<=m)时选最多的宝物,而一个子节点中只可以选择一个状态进行转移,每个节点有若干个子节点,问题就转换为分组背包,几个子节点就是几个分组背包,体积是选几个地点,价值是宝物价值。
#include <iostream>
#include <cstdio>
#include <string.h>
#define maxn 205
#define MAXN 1005

using namespace std;

int n,m,k,cnt;
int pp[maxn],cost[maxn],dp[maxn][maxn];
struct Node
{
int v,next;//v是儿子节点,next是兄弟节点
} edge[MAXN];

void addedge(int u,int v)
{
cnt++;
edge[cnt].v=v;
edge[cnt].next=pp[u];
pp[u]=cnt;
}
void dfs(int u)
{
int i,j,v;
dp[u][1]=cost[u];//初始化dp[u][1]
for(i=pp[u]; i!=0; i=edge[i].next)//访问兄弟节点,叶子节点退出
{
v=edge[i].v;
dfs(v);//递归没访问过的儿子节点
for(j=m; j>=0; j--)//01背包计算dp值
{

for(k=1; k<=j-(u!=0); k++)
{
dp[u][j]=max(dp[u][j],dp[v][k]+dp[u][j-k]);
}
}
}
}
int main()
{
int i,u;
while(scanf("%d%d",&n,&m),n|m)
{
cnt=0;
memset(pp,0,sizeof(pp));
for(i=1; i<=n; i++)
{
scanf("%d%d",&u,&cost[i]);
addedge(u,i);
}
memset(dp,0,sizeof(dp));
dfs(0);
printf("%d\n",dp[0][m]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: