【树形DP】 POJ 2486 Apple Tree

题目链接:  POJ 2486 Apple Tree

分析: 

      这题最重要的一个地方是可能会走回头路.

      那么,我们对某一结点可分为两种状态, 即访问其子结点后回来及不回来.

      当访问到某一结点的子结点时, 有以下三种情况:

      PS. dp[u][i][j]  表示到结点i已经走了j步,得到最多的苹果数. u=0 表示不回到该结点, u=1是回到该点.

      Ⅰ、从兄弟结点出发访问son结点, 要经过cnt,所以要+2到达son. 并且不再回到cnt.

      

     


      Ⅱ、直接从父亲访问son结点,所以到达son只需要 +1, 并且不再回到父亲结点

       


      Ⅲ、直接从cnt结点访问son结点, 访问son的整个树枝之后又回到父亲结点. 因些要+2.

     

      



代码:


#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>

using namespace std;
const int maxn=222;
vector<int>Tree[maxn];
int dp[2][maxn][maxn];  /// 1表示去过子结点回到原来的点, 0相反
int val[maxn];
bool vis[maxn];
int n,m;
void DFS(int cnt){
    vis[cnt]=true;
    int len=Tree[cnt].size();
    for(int i=0;i<=m;++i)
        dp[0][cnt][i]=dp[1][cnt][i]=val[cnt];
    for(int i=0;i<len;++i){
        int son=Tree[cnt][i];
        if(vis[son]) continue;
        DFS(son);
        for(int j=m;j>=0;--j)
            for(int k=0;k<=j;++k){
                dp[0][cnt][j+1]=max(dp[0][cnt][j+1],dp[1][cnt][j-k]+dp[0][son][k]);
                dp[0][cnt][j+2]=max(dp[0][cnt][j+2],dp[0][cnt][j-k]+dp[1][son][k]);
                dp[1][cnt][j+2]=max(dp[1][cnt][j+2],dp[1][cnt][j-k]+dp[1][son][k]);
            }
    }
}
int main(){
    while(~scanf("%d%d",&n,&m)){
        memset(dp,0,sizeof(dp));
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;++i){
            Tree[i].clear();
            scanf("%d",&val[i]);
        }
        for(int i=1;i<n;++i){
            int a,b; scanf("%d%d",&a,&b);
            Tree[a].push_back(b);
            Tree[b].push_back(a);   
        }
        DFS(1);
        printf("%d\n",dp[0][1][m]);
    }
    return 0;
}





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值