poj-2486-树形dp

来源:互联网 发布:淘宝替人代付用信用卡 编辑:程序博客网 时间:2024/05/16 05:40

dp[0][i][j]:在第i个节点,走j步,最后不返回i,得到的最多的苹果

dp[1][i][j]:在第i个节点,走j不,最后    返回i,得到的最多的苹果

若y是x的子节点:

dp[0][x][j+1]=max(dp[0][x][j+1],dp[1][x][jj]+dp[0][y][j-jj]);//在y上不返回
dp[0][x][j+2]=max(dp[0][x][j+2],dp[0][x][jj]+dp[1][y][j-jj]);//在y上返回
dp[1][x][j+2]=max(dp[1][x][j+2],dp[1][x][jj]+dp[1][y][j-jj]);

注意:题目没说一定必须走k步,则每运行到一个节点的时候,就把这个节点的所有的步数初始化为val[x]。

#include<iostream>#include<stdio.h>#include<string.h>#include<algorithm>#include<iostream>#include<vector>#include<set>#include<string>using namespace std;vector<int>old[1001];vector<int>now[1001];int vis[1001];int val[201];int n,k;int dp[2][201][301];//0代表不返回,1代表返回void change(int x){    int i;    vis[x]=1;    for(i=0;i<old[x].size();i++)    {        if(vis[old[x][i]])continue;        now[x].push_back(old[x][i]);        change(old[x][i]);    }}void dfs(int x){    int i,j,jj;    for(i=0;i<=k;i++)    dp[0][x][i]=dp[1][x][i]=val[x];    for(i=0;i<now[x].size();i++)    {        int y=now[x][i];        dfs(y);        for(j=k;j>=0;j--)        {            for(jj=0;jj<=j;jj++)            {                dp[0][x][j+1]=max(dp[0][x][j+1],dp[1][x][jj]+dp[0][y][j-jj]);                dp[0][x][j+2]=max(dp[0][x][j+2],dp[0][x][jj]+dp[1][y][j-jj]);                dp[1][x][j+2]=max(dp[1][x][j+2],dp[1][x][jj]+dp[1][y][j-jj]);            }        }    }}int main(){    int i,j;    int a,b;    while(~scanf("%d%d",&n,&k))    {        memset(dp,0,sizeof(dp));        for(i=1;i<=n;i++)        {            cin>>val[i];        }        memset(vis,0,sizeof(vis));        for(i=0;i<=n;i++)        {            old[i].clear();            now[i].clear();        }        for(i=1; i<n; i++)        {            scanf("%d%d",&a,&b);            old[a].push_back(b);            old[b].push_back(a);        }        change(1);        dfs(1);        cout<<dp[0][1][k]<<endl;    }    return 0;}


0 0