• poj2486


    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define MAXN 105
    using namespace std;
    
    int n,k,tot;
    int a[MAXN],h[MAXN];
    int f[MAXN][MAXN<<1][2];//那个子树,移动几次  是否回到根 
    
    struct node{
        int from,to,next;
    }e[MAXN<<1];
    
    void init(){
        tot=0;
        memset(h,-1,sizeof(h));
        memset(f,0,sizeof(f));
    }
    
    void add(int x,int y){
        tot++;
        e[tot].from=x;
        e[tot].to=y;
        e[tot].next=h[x];
        h[x]=tot;
    }
    //0表示回来根  1表示不必 
    int dfs(int now,int fa){
        for(int i=0;i<=k;i++)f[now][i][0]=f[now][i][1]=a[now];
        for(int i=h[now];i!=(-1);i=e[i].next){
            if(e[i].to!=fa){
            dfs(e[i].to,now);    
            //开始dp了喔    
                for(int j=k;j>=0;j--){
                    for(int p=1;p<=j;p++){
                        if(p>=2)f[now][j][0]=max(f[now][j][0],f[now][j-p][0]+f[e[i].to][p-2][0]);
                        if(p>=1)f[now][j][1]=max(f[now][j][1],f[now][j-p][0]+f[e[i].to][p-1][1]);
                        if(p>=2)f[now][j][1]=max(f[now][j][1],f[now][j-p][1]+f[e[i].to][p-2][0]);
                    }
                }            
            }
        }
    } 
    
    int main(){
        while(scanf("%d%d",&n,&k)==2){
            for(int i=1;i<=n;i++)scanf("%d",&a[i]);
            init();
            for(int i=1;i<n;i++){
                int x,y;scanf("%d%d",&x,&y);
                add(x,y);
                add(y,x);
            }
            dfs(1,1);
            cout<<f[1][k][1]<<endl;
        }    
    }
    View Code

    嘛,比较难想的dp(其实不是难想啦....就是复杂一点而已)

    嘛直接先套树形背包模板  但发现不足以表达所有状态....

    于是乎再加一维!!!!(是否一定在根节点)

    然后转移就好了

    1.一定在根节点

            1.其他子节点先到根,然后再转移当前子树

    2.不一定在根节点

            1.先往其他子树绕一圈回来,然后回来后再直接往下面走

            2.从当前子树绕一圈回来,然后再接着走

    然后这题就结束了

  • 相关阅读:
    【codevs4919】线段树练习4
    【51Nod1405】树上距离和 二次扫描与换根法
    【洛谷P1717】钓鱼
    【洛谷P1230】智力大冲浪
    【洛谷P1248】加工生产调度
    hdu 1195(搜索)
    hdu 1181(Floyed)
    hdu 1250(大整数)
    hdu 1180(广搜好题)
    hdu 1099(数学)
  • 原文地址:https://www.cnblogs.com/shatianming/p/12299469.html
Copyright © 2020-2023  润新知