树形DP +01背包(HDU 1011)

来源:互联网 发布:windows找不到chrome 编辑:程序博客网 时间:2024/05/17 06:56

题意:有n个房间,有n-1条道路连接着n个房间,每个房间都有若干个野怪和一定的能量值,有m个士兵从1房间入口进去,到达每个房间必须要留下若干士兵杀死所有的野怪,然后其他人继续走,(一个士兵可以杀死20只 野怪)问可以获得的最大能量值是多少?

分析:要想进入一个房间,必须把前面所有进过的房间的野怪都杀死,当某个房间的野怪数量是0的时候也需要至少派出一个人来进入这个房间来获得能量。

#include"stdio.h"#include"string.h"#include"stdlib.h"#include"algorithm"#include"math.h"#define M 222#define inf 0x3f3f3f3f#define eps 1e-10using namespace std;struct node{    int u,v,next;}edge[M*2];int t,head[M],dp[M][M],m,bug[M],value[M],num[M];void init(){    t=0;    memset(head,-1,sizeof(head));}void add(int u,int v){    edge[t].u=u;    edge[t].v=v;    edge[t].next=head[u];    head[u]=t++;}void dfs(int u,int f,int cost){    num[u]=(bug[u]+19)/20;    for(int i=num[u];i<=cost;i++)//当到达当前u节点的时候最多还余下cost士兵        dp[u][i]=value[u];//把该节点至少需要的士兵到最大的士兵全部赋值    for(int i=head[u];i!=-1;i=edge[i].next)    {        int v=edge[i].v;        if(v==f)continue;        dfs(v,u,cost-num[u]);//到达下一间房间还有的士兵数目        for(int j=cost;j>=num[u];j--)        {            for(int k=1;k<=j;k++)            {                if(k>=num[v]&&j-k>=num[u])//动态枚举状态搜索最大值                dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]);            }        }    }}int main(){    int n,i,a,b;    while(scanf("%d%d",&n,&m),n!=-1||m!=-1)    {        for(i=1;i<=n;i++)            scanf("%d%d",&bug[i],&value[i]);        init();        for(i=1;i<n;i++)        {            scanf("%d%d",&a,&b);            add(a,b);            add(b,a);        }        memset(dp,0,sizeof(dp));        if(m==0)        {            printf("0\n");            continue;        }        dfs(1,1,m);        printf("%d\n",dp[1][m]);    }}


0 0
原创粉丝点击