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

来源:互联网 发布:python安装视频 编辑:程序博客网 时间:2024/05/29 04:46

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\n",ans);    }    return 0;}

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 魔域手游宝宝亲密度不够怎么办 魔域手游怎么改密码忘了怎么办 魔域装备注灵怎么办 lol外服账号忘记了怎么办 美服lol下载慢怎么办 台服天堂2延迟怎么办 梦幻专用瑞兽没有泰山怎么办 冲错了游戏点券怎么办 新手玩联盟很菜怎么办 cf玩一会儿卡退怎么办 魔域先锋区封号了怎么办 吃了减肥药头疼怎么办 冬天没用完的霜怎么办 手表带起来大了怎么办 碰到舞警打人该怎么办 合租者偷了东西却没有证据怎么办 钥匙锁在房间了怎么办 家里门钥匙丢了怎么办 合租朝北晒衣服怎么办 卧室门钥匙丢了怎么办 邻居在我家防盗窗上凉被子怎么办 有钥匙打不开门怎么办 白色腈纶衣服洗完发黄怎么办 在部队有人整你怎么办 老公掉粪坑了你怎么办图片 好久没跑步腿疼怎么办 跑1000米要5分钟怎么办 孩子眼睛近视加散光怎么办 在部队混的差怎么办 2岁宝宝走路踮脚怎么办 宝宝走路膝盖弯曲不直怎么办 做了蛙跳大腿疼怎么办 跳完蛙跳腿疼怎么办 腿受凉了疼怎么办偏方 鸭子步蛙跳后腿疼怎么办 戴墨镜鼻子会红怎么办 校服黑色裙子染色了怎么办 新警培训时怀孕怎么办? 大学生欠了网贷怎么办? 车侧面底盘被刮怎么办 军人家属被打没人处理怎么办