poj 2486 APPLE TREE 树形dp+01背包

来源:互联网 发布:南风知我意七微19楼 编辑:程序博客网 时间:2024/05/17 02:29

题意:

求从根节点出发走K步经过的结点权值和最大

分析:

很容易想到dp【i】【j】表示i为根走j步的最优解,对于所有儿子结点跑一个01背包就ok

这时候会发现对于当前状态从i出发走j步回到i节点和不回到i节点对于状态转移是不一样的

所以加一维表示是否回到根节点(0----不回到 1-----回到)

那么转移方程:

dp[u][j][0]=max(dp[u][j][0],dp[u][j-k][1]+dp[v][k-1][0]);
        if(k>=2)
              dp[u][j][0]=max(dp[u][j][0],dp[u][j-k][0]+dp[v][k-2][1]);
              dp[u][j][1]=max(dp[u][j][1],dp[u][j-k][1]+dp[v][k-2][1]);

k-1/k-2 是从根结点到当前儿子结点的花费

ACcode:

#include <iostream>#include <cstring>#include <algorithm>#include <cstdio>#include <cmath>#include <cstring>#include <string>#include <vector>#define maxn 205#define inf 0x3f3f3f3f#define ll long longusing namespace std;int n,m,tmp;struct N{    int to,next;}my[maxn<<1];int dp[maxn][maxn<<1][2];int head[maxn],tot;void init(){    memset(head,-1,sizeof(head));    memset(dp,0,sizeof(dp));    tot=0;}void add(int u,int v){    my[tot].to=v;    my[tot].next=head[u];    head[u]=tot++;}void dfs(int u,int fa){    for(int i=head[u];i!=-1;i=my[i].next){        int v=my[i].to;        if(v==fa)continue;        dfs(v,u);        for(int j=m;j>=1;--j){            for(int k=1;k<=j;++k){                dp[u][j][0]=max(dp[u][j][0],dp[u][j-k][1]+dp[v][k-1][0]);                if(k>=2){                    dp[u][j][0]=max(dp[u][j][0],dp[u][j-k][0]+dp[v][k-2][1]);                    dp[u][j][1]=max(dp[u][j][1],dp[u][j-k][1]+dp[v][k-2][1]);                }            }        }    }}int main(){    while(scanf("%d%d",&n,&m)!=EOF){        init();        for(int i=1;i<=n;++i){            scanf("%d",&tmp);            for(int j=0;j<=m;++j)                dp[i][j][0]=dp[i][j][1]=tmp;        }        for(int i=1;i<n;++i){            int u,v;            scanf("%d%d",&u,&v);            add(u,v);            add(v,u);        }        dfs(1,-1);        cout<<max(dp[1][m][0],dp[1][m][1])<<'\12';    }    return 0;}


1 0
原创粉丝点击