• POJ 2392 Space Elevator(贪心+多重背包)


    POJ 2392 Space Elevator(贪心+多重背包)

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

    题意:

           题意:给定n种积木。每种积木都有一个高度h[i],一个数量num[i]。另一个限制条件,这个积木所在的位置不能高于limit[i],问能叠起的最大高度?

    分析:

           本题是一道多重背包问题, 只是每一个物品的选择不只要受该种物品的数量num[i]限制, 且该物品还受到limit[i]的限制.

    这里有一个贪心的结论:

           我们每次背包选取物品时都应该优先放置当前limit[i]值最小的积木(能够画个图看看,只是不太好证明该结论). 所以我们首先把全部积木按limit[i]的值进行从小到大的排序, 然后从1编号開始选积木就可以.

           以下就是多重背包的过程了.

           令dp[i][j]==x表示用前i个积木且总的高度<=j时能达到的最大高度为x.

           初始化: dp全为0.

           对于每种物品, 我们要做两种选择:

           1.    num[i]*high[i]>=limit[i]时, 做一次全然背包.

           2.    Num[i]*high[i]<limit[i]时, 须要把当前物品再分类, 然后做多次01背包就可以.

           终于所求: dp[n][j]的最大值. 当中j遍历[0,limit[n]]内全部数.

           注意: 本来按道理dp[i][j]的语义是<=j时, 而不是正好等于j时. 我们直接输出dp[n][limit[n]]就可以的. 可是本题有点特殊. 看以下这组数据:

    2

    5 11 3

    8 12 2

           相应的终于dp输出为:

    i=0 dp[i]=0

    i=1 dp[i]=0

    i=2 dp[i]=0

    i=3 dp[i]=0

    i=4 dp[i]=0

    i=5 dp[i]=5

    i=6 dp[i]=5

    i=7 dp[i]=5

    i=8 dp[i]=8

    i=9 dp[i]=8

    i=10 dp[i]=10

    i=11 dp[i]=10

    i=12 dp[i]=8

           为什么会得到上面奇怪的数据呢?

    由于当选择第1个物品(high[1]==5)时, 进行的背包过程仅仅做到了11高度就停了, 没有继续到全部数据. 所以终于须要遍历全部dp数据.

    AC代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=40000+5;
    
    int n;//木块种类
    struct Node//每种木块
    {
        int high,num,limit;
        bool operator<(const Node &rhs)const
        {
            return limit<rhs.limit;
        }
    }nodes[400+5];
    int dp[maxn];
    
    //一次01背包过程
    void ZERO_ONE_PACK(int cost,int limit)
    {
        for(int i=limit;i>=cost;i--)
            dp[i] = max(dp[i], dp[i-cost]+cost);
    }
    
    //一次全然背包过程
    void COMPLETE_PACK(int cost,int limit)
    {
        for(int i=cost;i<=limit;i++)
            dp[i] = max(dp[i], dp[i-cost]+cost);
    }
    
    //一次多重背包过程
    void MULTIPLY_PACK(int cost,int limit,int num)
    {
        if(cost*num>=limit)
        {
            COMPLETE_PACK(cost,limit);
            return ;
        }
    
        int k=1;
        while(k<num)
        {
            ZERO_ONE_PACK(cost*k,limit);
            num-=k;
            k*=2;
        }
        ZERO_ONE_PACK(cost*num,limit);
    }
    
    int main()
    {
        while(scanf("%d",&n)==1)
        {
            //读取输入+排序
            for(int i=1;i<=n;i++)
                scanf("%d%d%d",&nodes[i].high,&nodes[i].limit,&nodes[i].num);
            sort(nodes+1,nodes+n+1);
    
            //初始化dp+递推
            memset(dp,0,sizeof(dp));
            for(int i=1;i<=n;i++)
                MULTIPLY_PACK(nodes[i].high, nodes[i].limit, nodes[i].num);
    
            //统计结果输出
            int ans=0;
            for(int i=0;i<=nodes[n].limit;i++)
                ans=max(ans,dp[i]);
            printf("%d
    ",ans);
        }
        return 0;
    }
    

  • 相关阅读:
    Algs4-2.1.23纸牌排序
    python字符串加颜色区别
    python学习之字典
    python学习之while语句
    python学习之字符串变量
    python学习之列表语法
    python简单实现用户表单登录
    python学习之安装模块
    python学习之认识字符串
    python学习之for语句
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/6805946.html
Copyright © 2020-2023  润新知