hdu1011

来源:互联网 发布:淘宝网冬装女装外套 编辑:程序博客网 时间:2024/06/10 21:22

树形dp背包

对任一节点,取得最大值相当于在确定根节点消耗之后对所有子树进行01背包,获得1~m每个状态的最大值,然后向上递归,直至找到根节点,此时求得的最大值即为所求

状态转移方程:dp[i][t]=max(dp[i][t],dp[i][k]+dp[son[i]][t-k])(k=0,1,2......)

#include <iostream>using namespace std;int map[105][105];int v[105];int w[105];int dp[105][105];int n,m;void build(int s)//建树,此题比较坑的地方,即给的节点不一定是先父节点后子节点的顺序{    for (int i=1;i<=n;i++)    {        if (map[s][i]==1)        {            map[i][s]=0;            build(i);        }    }}int max(int a,int b){    return a>b?a:b;}void get(int s){    for (int i=w[s];i<=m;i++)        dp[s][i]=v[s];    for (int i=1;i<=n;i++)    {        if (map[s][i]==1)        {            get(i);            for (int t=m;t>w[s];t--)            {                for (int k=t-1;k>=w[s];k--)                {                    dp[s][t]=max(dp[s][t],dp[s][k]+dp[i][t-k]);                }            }        }    }   }int main(){    while (scanf("%d%d",&n,&m)&&n!=-1)    {        memset(map,0,sizeof(map));        memset(dp,0,sizeof(dp));        for (int i=1;i<=n;i++)        {            scanf("%d%d",&w[i],&v[i]);            w[i]=(w[i]+19)/20;        }        for (int i=1;i<n;i++)        {            int k,t;            scanf("%d%d",&k,&t);            map[k][t]=map[t][k]=1;        }        build(1);        get(1);        if (m==0)            cout<<0<<endl;        else            cout<<dp[1][m]<<endl;    }}


0 0
原创粉丝点击