zoukankan      html  css  js  c++  java
  • [HDU] 1561 The more, The Better 树形DP加01分组背包

    题目链接:

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

    方法:

    表面上看输入是一个森林的结构,其实可以用0节点作为父节点将森林中所有的树串起来作为一个树,然后开始DP,设F(P,x)是P为根的子树上选x个能获得的最大值的集合。

          {

          {0}; x==0

    F(P,x) =

          {v+P的价值|v属于{F(s,x1)|s是p的直接子节点 && 0<=x1<min( (p为根? x+1:x),m)   }跑一个以一个s作为分组的01分组背包形成的集合};0<x<=min(((p为根? m:m-1)),  p那里最多选出多少)

          }

    代码:

    #include <iostream>
    #include <queue>
    #include<algorithm>
    using namespace std;
    int n,m;
    struct Staff
    {
        int cost;
        int value;
    };
    struct Adge
    {
        int vetex;
        Adge* nextAdge;
    };
    struct Node
    {
        Adge* firstAdge;
        bool isRoot;
        int value;
        Staff staff[201];
        int StaffCount;
        int maxChose;
    };
    Node nodes[201];
    int myMax(int x,int y)
    {
        return x>=y? x:y;
    }
    void createAdge(int father,int son)
    {
        Adge* adge = (Adge*)(malloc(sizeof(Adge)));
        adge->vetex = son;
        if(nodes[father].firstAdge==NULL)
            adge->nextAdge = NULL;
        else
            adge->nextAdge = nodes[father].firstAdge;
        nodes[father].firstAdge = adge;    
    }
    void DFSDP(int root)
    {
        Adge* adge = nodes[root].firstAdge;
        int v,sonCount=0;
        int innerDP[205];
        memset(innerDP,0,sizeof(innerDP));
        while(adge!=NULL)
        {
            v= adge->vetex;
            DFSDP(v);
            nodes[root].maxChose+=nodes[v].maxChose;
            for(int i=m;i>=0;i--)
                for(int j=1;j<=nodes[v].StaffCount;j++)
                    if(nodes[v].staff[j].cost<=i)
                        innerDP[i] = myMax(innerDP[i-nodes[v].staff[j].cost]+nodes[v].staff[j].value,innerDP[i]);
            adge=adge->nextAdge;
            sonCount++;
        }
        if(sonCount==0)
        {
            nodes[root].StaffCount++;
            Staff st;
            st.cost=1;
            st.value=nodes[root].value;
            nodes[root].staff[nodes[root].StaffCount]=st;
        }
        else
        {
            int base = root==0?1:0;
            for(int i=0;i<m+base&&i<nodes[root].maxChose+base;i++)
            {
                nodes[root].StaffCount++;
                Staff st;
                st.cost=i+(1-base);
                st.value=innerDP[i]+nodes[root].value*(1-base);
                nodes[root].staff[nodes[root].StaffCount]=st;
            }
        }
    }
    void main()
    {
        Staff st;
        st.cost=st.value = 0;
        while(scanf("%d %d",&n,&m)&&!(n==0 && m==0))
        {
            for(int i=0;i<=200;i++)
            {
                nodes[i].isRoot= false;
                nodes[i].firstAdge=NULL;
                nodes[i].StaffCount=1;
                nodes[i].staff[nodes[i].StaffCount] = st;
                nodes[i].maxChose=1;
            }
            int father,value;
            for(int i=1;i<=n;i++)
            {
                scanf("%d %d",&father,&value);
                nodes[i].isRoot = father==0 ?true :false;
                nodes[i].value = value;
                createAdge(father,i);
            }
            DFSDP(0);
            for(int i=0;i<=nodes[0].StaffCount;i++)
            {
                if(nodes[0].staff[i].cost==m)
                {
                    cout<<nodes[0].staff[i].value<<endl;
                    break;
                }
            }
        }
    }
    

     感想:实在不知道这个报告应该怎么描述,反正就是知道

  • 相关阅读:
    键盘事件
    冒泡事件-捕获事件-阻止事件
    Date()常用属性
    dom树节点的增删改插
    boost/c++11 变量类型打印、相等判断以及成员函数指针相关
    c++ std:call_once 与 单例模式实现
    c++11 异步编程 std::async
    c++ STL中一些常用函数/模板
    c++11 std::atomic 原子操作
    C++ std::atomic_flag 实现spinLock
  • 原文地址:https://www.cnblogs.com/kbyd/p/3243629.html
Copyright © 2011-2022 走看看