您的位置:首页 > 其它

HDOJ 1561 The more, The Better(树形DP)

2013-02-22 00:45 483 查看
思路:

有依赖的背包、泛化背包的思想,和“金明的预算方案”那题是一样的。

dp[u][i]表示u为根节点的子树,要攻击i个城堡所获得的最大金钱数目。其中u城堡是已经攻下来的。

则dp[u][i]=max(dp[u][i],dp[v][i-1]+val[v]);

题目中设置出发点位0,这样的话就可以把森林变成一个棵树,方便于解题。

解一:采用了泛化物品的并的O(n*V)优化解法,15ms

#include<iostream>
#include<algorithm>
usingnamespacestd;

constintMAXN=210;

structedge{
intv,c;
edge*next;
}*V[MAXN],ES[MAXN*2];

intEC,dp[MAXN][MAXN],val[MAXN];
boolvis[MAXN];

voidaddedge(intu,intv)
{
ES[++EC].next=V[u];
V[u]=ES+EC;V[u]->v=v;
}

voidinitdata(intn)
{
EC=0;
memset(V,0,sizeof(V));
memset(vis,false,sizeof(vis));

for(intu=1;u<=n;++u)
{
intv;
scanf("%d%d",&v,&val[u]);
addedge(v,u);
}
}

voidtreedp(intu,intvol)
{
vis[u]=true;

for(edge*e=V[u];e;e=e->next)
{
if(vis[e->v])
continue;

for(inti=vol;i>=0;--i)
dp[e->v][i]=dp[u][i];

treedp(e->v,vol-1);

for(inti=vol;i>=1;--i)
dp[u][i]=max(dp[u][i],dp[e->v][i-1]+val[e->v]);
}
}

intmain()
{
intn,m;
while(scanf("%d%d",&n,&m)&&n&&m)
{
initdata(n);
memset(dp[0],0,sizeof(dp[0]));
treedp(0,m);
printf("%d\n",dp[0][m]);
}
return0;
}

解法二:普通解法O(n*V*V)

#include<iostream>
#include<algorithm>
usingnamespacestd;

constintMAXN=210;

structedge{
intv,c;
edge*next;
}*V[MAXN],ES[MAXN*2];

intEC,dp[MAXN][MAXN],val[MAXN];
boolvis[MAXN];

voidaddedge(intu,intv)
{
ES[++EC].next=V[u];
V[u]=ES+EC;V[u]->v=v;
}

voidinitdata(intn)
{
EC=0;
memset(V,0,sizeof(V));
memset(vis,false,sizeof(vis));

for(intu=1;u<=n;++u)
{
intv;
scanf("%d%d",&v,&val[u]);
addedge(v,u);
}
memset(dp,0,sizeof(dp));
}

voidtreedp(intu,intvol)
{
vis[u]=true;

for(edge*e=V[u];e;e=e->next)
{
if(vis[e->v])
continue;

treedp(e->v,vol-1);

for(inti=vol;i>=1;--i)
for(intj=1;j<=i;++j)
dp[u][i]=max(dp[u][i],dp[u][j-1]+dp[e->v][i-j]+val[e->v]);
}
}

intmain()
{
intn,m;
while(scanf("%d%d",&n,&m)&&n&&m)
{
initdata(n);
treedp(0,m);
printf("%d\n",dp[0][m]);
}
return0;
}


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