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;
}

POJ 2392 Space Elevator(贪心+多重背包)的更多相关文章

  1. POJ 2392 Space Elevator(多重背包)

    显然塔的总高度不会超过最大的a[i],而a[i]之前的可以到达的高度 是由a值更小的块组成,所以按照a从小到大的顺序去转移. 然后就是多重背包判断存在性了,几乎和coin那题一样. 数据没coin丧病 ...

  2. POJ 2392 Space Elevator 贪心+dp

    题目链接: http://poj.org/problem?id=2392 题意: 给你k类方块,每类方块ci个,每类方块的高度为hi,现在要报所有的方块叠在一起,每类方块的任何一个部分都不能出现在ai ...

  3. POJ 2392 Space Elevator(多重背包变形)

    Q: 额外添加了最大高度限制, 需要根据 alt 对数据进行预处理么? A: 是的, 需要根据 alt 对数组排序 Description The cows are going to space! T ...

  4. poj 2392 Space Elevator(多重背包+先排序)

    Description The cows are going to space! They plan to achieve orbit by building a sort of space elev ...

  5. POJ 2392 Space Elevator 背包题解

    多重背包.本题不须要二分优化.相对简单点.由于反复数十分小,小于10. 而添加一个限制每种材料的高度做法.假设使用逆向填表,那么仅仅须要从这个高度往小递归填表就能够了. 还有就是注意要排序,以限制高度 ...

  6. poj[2392]space elevator

    Description The cows are going to space! They plan to achieve orbit by building a sort of space elev ...

  7. POJ 2392 Space Elevator DP

    该题与POJ 1742的思路基本一致:http://www.cnblogs.com/sevenun/p/5442279.html(多重背包) 题意:给你n个电梯,第i个电梯高h[i],数量有c[i]个 ...

  8. poj 2392 建塔(多重背包+不定上界)

    http://blog.csdn.net/libin56842/article/details/9492351 这次比较理解那个!dp[j]是为了什么,因为是滚动数组,没有这个的话used那边会出问题 ...

  9. POJ 3260 The Fewest Coins(多重背包+全然背包)

    POJ 3260 The Fewest Coins(多重背包+全然背包) http://poj.org/problem?id=3260 题意: John要去买价值为m的商品. 如今的货币系统有n种货币 ...

随机推荐

  1. docker从零开始网络(五)null网络

    禁用容器的网络连接 预计阅读时间: 1分钟 如果要完全禁用容器上的网络堆栈,可以--network none在启动容器时使用该标志.在容器内,仅创建环回设备.以下示例说明了这一点. 1.创建容器. [ ...

  2. runtimeService.startProcessInstanceById("process:6:55036", 2222, variables) SQL语句

    JAVA: variables:{ user_flow_start_dept : "3333"} runtimeService.startProcessInstanceById(& ...

  3. 360开源的pika

    http://www.360doc.com/content/16/0531/14/13247663_563808424.shtml https://github.com/Qihoo360/pika/b ...

  4. MySQL数据库中的Date,DateTime,int,TimeStamp和Time类型的对比

    DATETIME 用在你需要同时包含日期和时间信息的值时.MySQL检索并且以'YYYY-MM-DD HH:MM:SS'格式显示DATETIME值,支持的范围是'1000-01-01 00:00:00 ...

  5. js 之面向对象

    对象 是什么? 对象就是一个整体,对外提供一些操作,比如:电视机(不用知道内部的构造,只知道怎么用) 面向对象 是什么? 使用对象时,只关注对象提供的功能,不关心内部细节,比如:操作电视机(只知道用遥 ...

  6. C指针详解

    前言:复杂类型说明 要了解指针,多多少少会出现一些比较复杂的类型,所以我先介绍一下如何完全理解一个复杂类型,要理解复杂类型其实很简单,一个类型里会出现很多运算符,他们也像普通的表达式一样,有优先级,其 ...

  7. 洛谷 P1316 丢瓶盖【二分答案】

    题目描述 陶陶是个贪玩的孩子,他在地上丢了A个瓶盖,为了简化问题,我们可以当作这A个瓶盖丢在一条直线上,现在他想从这些瓶盖里找出B个,使得距离最近的2个距离最大,他想知道,最大可以到多少呢? 输入输出 ...

  8. Codeforces 180C. Letter

    题目链接:http://codeforces.com/problemset/problem/180/C 题意: 给你一个仅包含大写字母和小写字母的字符串,你可以将让小写字母转化为大写字母,大写字母转化 ...

  9. 训练指南 UVA - 11324(双连通分量 + 缩点+ 基础DP)

    layout: post title: 训练指南 UVA - 11324(双连通分量 + 缩点+ 基础DP) author: "luowentaoaa" catalog: true ...

  10. Oracle的锁

    Oracle数据库中的锁机制 数据库是一个多用户使用的共享资源.当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况.若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数 ...