雨へ痕
下一站路口,未知的道路

这个题目是说 每个点有权值,有些点的得到需要先得到某点,问你选M个点能够得到的最大值

很明显是有依赖的背包,而且应该是有依赖中有依赖(虽然我觉得题目并没有很明确地说)~

这样的话 我们就构建dp[i][j],i为i号点,j为它选了里面的几个点。。。。。

这样的话 我们就发现其实是个树,点的值取决于子点的选法。

方程dp[k][j]=max(dp[k][j],dp[k][j-kk]+dp[t[k][i]][kk])

表示在第i个k的子点中选kk个点加上目前k号点选j-kk个点与直接在k号点选j个点谁更优。。。

我们可以知道dp[k][1]=val[k],因为选一个点的话必须选自己 = =

于是这样的题可以有两种基本写法,一是先确定了1的地位(这样或许算是常数优化),二是马后炮最后才补上这个val,第二种更好理解 所以附上第一种的代码~~

#include <stdio.h>
#include
<stdlib.h>
#include
<string.h>
#include
<math.h>
#define tt int
inline tt max(tt a,tt b)
{
return a>b?a:b;
}

inline tt min(tt a,tt b)
{
return a<b?a:b;
}

int dp[205][205];
int t[205][205];
int top[205];
int v[205];
int m;

void dfs(int k)
{
int i,j,kk;
v[k]
=1;
for(i=0;i<=top[k];i++)
{
if(!v[t[k][i]]) dfs(t[k][i]);
for(j=m;j>=2;j--) //只有2后面的状态需要更新
{
for(kk=1;kk<j;kk++)
{
if(dp[t[k][i]][kk]!=-1 && dp[k][j-kk]!=-1)
{
dp[k][j]
=max(dp[k][j],dp[k][j-kk]+dp[t[k][i]][kk]);
}
}
}
}
}

int main()
{
int n,i,j,k,ii,jj,sum,ans;
int x,y,z;
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n+m==0) break;
for(i=0;i<=n;i++) top[i]=-1;
dp[
0][1]=0; //自己为空点
for(i=1;i<=n;i++)
{
scanf(
"%d%d",&x,&y);
t[x][
++top[x]]=i;
dp[i][
1]=y;
}
for(i=0;i<=n;i++)
{
dp[i][
0]=0; // 0为不选任何一个点~
for(j=2;j<=m;j++)
{
dp[i][j]
=-1;
}
v[i]
=0;
}
m
++;//提前加一个点,就是0号
dp[0][m]=-1;
dfs(
0);
printf(
"%d\n",dp[0][m]);
}
return 0;
}
posted on 2011-04-28 23:14  雨^痕  阅读(808)  评论(2编辑  收藏  举报