HDU - 1561(树形dp+背包问题)

题目:click
每个城堡被攻克,必须之前有一个特定的城堡被攻克,才能攻占这个城堡。
形成了一种子节点与父节点的关系,联想到树形dp取解决。
走子节点必先走其父亲节点,一次建树,若无则父亲节点为0;
dp[i][j]:表示以i为节点,取j个城堡宝藏获得的最大值。

#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<map>
#include<algorithm>
#include<queue>
#define MAX_len 50100*4
using namespace std;
typedef long long ll;
int dp[210][210];// 第i个节点 收集了j个 的最大值
vector<int>hh[210];
int a[210];
int n,m;
bool vis[210];
void dfs(int root)
{
    if(vis[root])
        return ;
    vis[root]=true;
    dp[root][1]=a[root];
    for(int i=0;i<hh[root].size();i++)
    {
        int v=hh[root][i];
        if(vis[v])
            continue;
            dfs(v);
            for(int j=m+1;j>=2;j--)
            {
                for(int k=1;k<j;k++)
                    dp[root][j]=max(dp[root][j],dp[root][j-k]+dp[v][k]);
            }
    }
}
int main()
{
    while(scanf("%d %d",&n,&m)&&(n||m))
    {
        memset(vis,false,sizeof(vis));
        memset(dp,0,sizeof(dp));
        a[0]=0;
        int i,j,k;
        for(i=0;i<=n;i++)
            hh[i].clear();
        for(i=1;i<=n;i++)
        {
            int x;
            scanf("%d %d",&x,&a[i]);
            {
                hh[i].push_back(x);
                hh[x].push_back(i);
            }
        }
        dfs(0);
        printf("%d\n",dp[0][m+1]);
    }
    return 0;
}
发布了72 篇原创文章 · 获赞 19 · 访问量 7500

猜你喜欢

转载自blog.csdn.net/weixin_43958964/article/details/104599005
今日推荐