• poj 2486 Apple Tree 夜


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

    树形DP 我一般都是先用邻接表保存树 然后用的都是子树和所有兄弟树的dp方法

    自己感觉理解也行呀 但是没见有多少人用呢,也许自己有点另类

    老是出错 思维能力还是不够 越来越感觉acm是在练一个人的思维了

    题目大意:

    给一个树 节点有一定数目的苹果

    人在1(根点)最多走K步 问最多可以得到多少苹果

    思路:

    ans[i][j][0] 表示包括i在内所以其子节点和右边兄弟树 可以走j步 可以存在不回来的情况 的最佳答案

    ans[i][j]][1] 这个必须都回来

    代码及其注释:

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<queue>
    #include<cmath>
    #include<stack>
    #include<algorithm>
    #define LL long long
    
    using namespace std;
    
    const int N=105;
    const int MIN=-100000000;
    struct node
    {
        struct tt *next;
    }mem[N];
    struct tt
    {
        int j;
        struct tt *next;
    };
    bool had[N];
    bool link[N][N];
    int applenum[N];
    int ans[N][N*2][2];
    int a[3][3][3];
    void build(int i,int j)
    {
        struct tt *t=new tt;
        t->j=j;
        t->next=mem[i].next;
        mem[i].next=t;
    }
    void Dele(int n)
    {
        struct tt *t;
        for(int i=1;i<=n;++i)
        {//cout<<i<<endl;
            while(mem[i].next!=NULL)
            {//cout<<"iii"<<endl;
                t=mem[i].next;
                mem[i].next=t->next;
                delete t;
            }
        }
    }
    int dp(struct tt *t,int k,int back)
    {
       if(t==NULL)//各种 无法走的情况
       return 0;
       if(k<0)
       return 0;
       if(back==1&&k<1)
       return 0;
       if(ans[t->j][k][back]!=-1)
       return ans[t->j][k][back];
       int itemp=0;
       int w=0;
       for(int i=0;i<=k;++i)
       {
           if(i>=1)
           w=applenum[t->j];//要回去时 只有可以回去 才能加上本节点的苹果树
           itemp=max(itemp,w+dp(mem[t->j].next,i-2,1)+dp(t->next,k-i-1,back));//给子树一部分 往兄弟传一部分 注意路径需要的步数减去
           if(back==0)
           {
               w=applenum[t->j];//这是子树不用回来的 其他差不多
               itemp=max(itemp,w+dp(mem[t->j].next,i-1,0)+dp(t->next,k-i-1,1));
           }
       }
       ans[t->j][k][back]=itemp;
       if(t->next!=NULL)
       ans[t->j][k][back]=max(ans[t->j][k][back],dp(t->next,k,back));//如果不走此节点
       return  ans[t->j][k][back];
    }
    void dfs(int x,int n)
    {
        had[x]=true;
        for(int i=1;i<=n;++i)
        {
            if(link[x][i]&&!had[i])
            {
                build(x,i);//建立单向树
                dfs(i,n);
            }
        }
    }
    int main()
    {
        int n,k;
        while(scanf("%d %d",&n,&k)!=EOF)
        {
            for(int i=1;i<=n;++i)
            {
                scanf("%d",&applenum[i]);
            }
            memset(link,false,sizeof(link));
            for(int i=1;i<n;++i)
            {
                int x,y;
                scanf("%d %d",&x,&y);
                link[x][y]=link[y][x]=true;
            }
            if(n==1)
            {
                printf("%d\n",applenum[1]);
                continue;
            }
            memset(had,false,sizeof(had));
            dfs(1,n);
            memset(ans,-1,sizeof(ans));
            printf("%d\n",applenum[1]+dp(mem[1].next,k-1,0));
            Dele(n);
        }
    }
    

      

  • 相关阅读:
    Docker优势
    jdk-tomcat-jenkens 安装
    SQL-2--TRIGGER
    边工作边刷题:70天一遍leetcode: day 92
    边工作边刷题:70天一遍leetcode: day 39
    边工作边刷题:70天一遍leetcode: day 96
    边工作边刷题:70天一遍leetcode: day 1
    边工作边刷题:70天一遍leetcode: day 94
    边工作边刷题:70天一遍leetcode: day 95
    边工作边刷题:70天一遍leetcode: day 97
  • 原文地址:https://www.cnblogs.com/liulangye/p/2605514.html
Copyright © 2020-2023  润新知