zoukankan      html  css  js  c++  java
  • hdu 1561 The more, The Better 夜

    树形DP 此代码还可以优化

    ans[i][j] 代表以i节点的子树 攻j个城堡 的最优值

    详解见代码注释

    http://acm.hdu.edu.cn/showproblem.php?pid=1561

    #include<iostream>
    #include<string>
    #include<string.h>
    #include<queue>
    #include<math.h>
    #include<algorithm>
    #include<vector>
    #include<stdio.h>
    #define Max 0x7ffffff

    using namespace std;

    int ans[211][211];
    int value[211];//第n 个城堡的价值
    struct node
    {
        struct tt *next;
    }mem[201];//用邻接表储存 树
    struct tt
    {
        struct tt *next;
        int k;
    };
    inline void build(int i,int j)//建树
    {
        struct tt *t=new tt;
        t->k=j;
        t->next=mem[i].next;
        mem[i].next=t;
    }
    inline void free(int n)//释放空间
    {
        struct tt *t,*w;
        for(int i=0;i<=n;i++)
        {
            t=mem[i].next;
            mem[i].next=NULL;//不能忽略
            while(t!=NULL)
            {
                w=t->next;
                delete(t);
                t=w;
            }
        }
    }
    int dp(struct tt *&t,int j)
    {
        if(t==NULL)//搜到此节点为空时
        {
            if(j==0)//如果还需0个城堡 正好满足 所以 为值0
            return 0;
            return -Max;//否则 返回极小
        }
        int i=t->k;//获取节点数值
        if(ans[i][j]!=-1)//避免重复
        return ans[i][j];
        if(j==0)//攻0个城堡且节点不为空 值为0
        {
            ans[i][j]=0;
            return ans[i][j];
        }
            if(j==1)攻1个城堡两种可能 攻节点本身 或者从兄弟节点中选

            {
                ans[i][j]=max(dp(t->next,j),value[i]);
                return ans[i][j];
            }

            //你猜
            ans[i][j]=dp(t->next,j);//可能本节点不选 完全选从其兄弟节点中选
            for(int l=0;l<j;l++)//选本节点 再从其子结点 和兄弟节点中选择
            {
                ans[i][j]=max(ans[i][j],dp(mem[i].next,l)+dp(t->next,j-1-l)+value[i]);
            }
            if(ans[i][j]>=0)
            return ans[i][j];
            ans[i][j]=min(ans[i][j],-Max);
            return ans[i][j];
    }
    int main()
    {

        int n,m,i,j;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            if(n==0&&m==0)
            break;
            for(i=1;i<=n;i++)
            {
                scanf("%d%d",&j,&value[i]);
                build(j,i);
            }
            memset(ans,-1,sizeof(ans));
            if(mem[0].next==NULL)
            {
                printf("0\n");
                continue;
            }

            printf("%d\n",max(0,dp(mem[0].next,m)));
            free(n);
        }
        return 0;
    }

  • 相关阅读:
    Idea破解2019
    Navicat Premium 12破解激活
    Java高并发程序设计学习笔记(十一):Jetty分析
    Java高并发程序设计学习笔记(十):并发调试和JDK8新特性
    Java高并发程序设计学习笔记(九):锁的优化和注意事项
    Java高并发程序设计学习笔记(八):NIO和AIO
    Java高并发程序设计学习笔记(七):并行设计模式
    Java高并发程序设计学习笔记(六):JDK并发包(线程池的基本使用、ForkJoin)
    推荐一套WPF主题皮肤
    WPF中的动画——(五)关键帧动画
  • 原文地址:https://www.cnblogs.com/liulangye/p/2280578.html
Copyright © 2011-2022 走看看