HDU 1561 The more, The Better

链接:http://acm.hdu.edu.cn/showproblem.php?pid=1561

这题是一道树形DP(依赖背包);这是我学树形DP的做的第一题,这种背包问题的物品间存在某种“依赖”的关系。也就是说,i依赖于j,表示若选物品i,则必须选物品j。为了简化起见,我们先设没有某个物品既依赖于别的物品,又被别的物品所依赖;另外,没有某件物品同时依赖多件物品。

对于这种背包我们可以建立成一棵树,父节点就是子节点所要依赖的;根据题意知道我们选择如果要打该节点,那么必要打掉该父节点;

如果打父节点,总共还剩N次可以打的机会,那么我们可以对于子节点是打还是不打,打得时候可以分给该节点几次,我们就从这几次中找出最优解;

View Code
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
vector<int>list[224];
int dp[224][224];
int value[224];
void DFS( int n ,int M )//M代表攻击该节点时还剩多少次
{
int len = list[n].size();
dp[n][1] = value[n];// 攻击该节点能够得到的财富值
for( int i = 0 ; i < len ; i++ )//继续攻击该节点下的子节点
{
if( M > 1 )
DFS( list[n][i] ,M -1 );
for( int j = M ; j >= 1 ; j-- )// 孩子节点攻击的次数
{
int v = j + 1;
for( int k = 1; k < v ; k++ )// 从孩子节点中找攻击J次的最优值
{
if( dp[n][v] < dp[n][v-k] + dp[list[n][i]][k] )
dp[n][v] = dp[n][v-k] + dp[list[n][i]][k];
}
}
}
}
int main( )
{
int n ,m ,start,end;
while( scanf( "%d%d",&n ,&m ),n||m )
{
memset( dp , 0 , sizeof( dp ) );
memset( value , 0 , sizeof( value ) );
for( int i = 0 ; i <= n ; i++ )
{
list[i].clear( );
}
for( int i = 1 ; i <= n ; i++ )
{
scanf( "%d%d",&start , &value[i] );
list[start].push_back( i );
}
DFS( 0 , m+1 );
// printf( "afsa" );
printf( "%d\n",dp[0][m+1] );
}
return 0;
}

 

你可能感兴趣的:(more)