poj2486Apple Tree(树形dp)

src: http://poj.org/problem?id=2486

思路:就像多重背包一样,dfs过子树后,子树就有了各种大小的代价,然后动态规划根的大小即可;

ac代码:

 

#include <iostream>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<functional>
#include<utility>
#include<string>
#include<string.h>
#include<vector>
#include<iomanip>
#include<stack>
using namespace std;
#define FOR(i,a,b) for(int i=a;i<=b;i++)
const int inf=99999999;

int n,k,dp[105][2][205],val[105],vis[105];//dp[i][0][k]表示从i开始出发走k步不回到i的最大值,1表示回到i
vector<int>head[105];

void init(){memset(dp,0,sizeof(dp));FOR(i,1,n)head[i].clear();memset(vis,0,sizeof(vis));}
void add_edge(int u,int v){head[u].push_back(v);head[v].push_back(u);}
void dfs(int u)
{
    FOR(i,0,k)dp[u][0][i]=dp[u][1][i]=val[u];
    vis[u]=1;
    for(int i=0;i<head[u].size();i++){
        int v=head[u][i];
        if(vis[v]==1)continue;
        dfs(v);
        for(int j=k;j>=0;j--){
            for(int t=0;t<=j;t++){
                dp[u][1][j+2]=max(dp[u][1][j+2],dp[u][1][j-t]+dp[v][1][t]);
                dp[u][0][j+2]=max(dp[u][0][j+2],dp[u][0][j-t]+dp[v][1][t]);
                dp[u][0][j+1]=max(dp[u][0][j+1],dp[u][1][j-t]+dp[v][0][t]);
            }
        }
    }
}

int main()
{
    std::ios::sync_with_stdio(false);
    while(cin>>n>>k){
        init();
        int a,b;
        FOR(i,1,n)cin>>val[i];
        for(int i=1;i<n;i++){cin>>a>>b;add_edge(a,b);}
        dfs(1);
        cout<<max(dp[1][0][k],dp[1][1][k])<<endl;
    }
    return 0;
}

 

posted @ 2018-05-07 11:03  WindFreedom  阅读(194)  评论(0)    收藏  举报