上一篇主要介绍了贪心算法的内容和活动选择问题。本篇主要介绍最优装载问题和最小延迟调度问题
1、最优装载问题
什么是最优装载问题
类似于0-1背包问题那样,有n个集装箱1,2,…,n装上轮船,集装箱i的质量wi,轮船装载重量限制为C,无体积限制。问如何装使得上船的集装箱最多?
这个和前面介绍的完全背包和0-1背包问题差不多一样。然而那些问题是有重量和价值的。这个最优装载问题是只关乎于重量对价值没有要求。而完全背包和0-1背包问题的时间复杂度就是指数量。而对于它们的子问题就存在多项式时间算法,例如,这个最优装载问题就存在一个多项式时间算法。
下面对于这个问题举个例子
有5个物品:w1=4,w2=6,w3=2,w4=8,w5=5。轮船装载重量限制为11
这个问题的解是:1,3,5
下面对问题进行建模:
设<x1,x2,…,xn>表示解向量,xi=0,1,xi=1当且仅当第i个集装箱装上船
那么目标函数就是装的箱子的个数的最大值,而约束条件就是装的箱子重量的和不能超过重量限制
接下来用贪心算法来解最优装载问题
用贪心算法来解最优装载问题
大家可以想想,用什么贪心策略来解这个问题。我相信大家一定是有想法的。
大家想的是不是这个贪心策略:轻者优先。
也就是先将集装箱进行升序排序,按照标号由小到大装箱,直到装入下一个箱子将使得集装箱总重超过轮船装在重量限制,则停止。
下面我们对这个贪心策略进行证明
数学归纳法证明贪心策略
首先将集装箱从轻到重记为1,2,…,n
首先进行归纳基础:
当k=1时,证明存在最优解包含物品1。
如若不然,我们找到一个物品j替换物品1。使其成为最优解A
我们用1来替换j,使其成为最优解A’
因为w1<=wj,如果A是最优解。那么A’也是最优解。因为这个升序之后的1号箱子质量最小。所以是可以放进去的。
因此归纳基础成立
下面我们进行归纳步骤:
假设命题对k为真,证明对k+1也为真
算法执行到第k步,选择了i1=1,i2,…,ik,根据归纳假设存在最优解包括i1,i2,…ik。然后我们对这个归纳假设进行改造。
我们把i1提出去,将ik+1加进去。因此得到i2,i3,…,ik+1这k个箱子对于命题成真。
我们将i2,i3,…,ik+1设为I’,根据归纳假设I’是一个最优解,因此我们有I=I’∪{1}。下面我们证明这个I是原始输入的最优解。
如若不然,则存在一个包含1的关于N的最优解I1,(如果I1中没有1,则用1替换I1中的第一个元素得到的解也是最优解),且|I1|>|I|;因此就会有|I1-{1}|>|I-{1}|。好,下面我们把I1和I的1号箱子全部取走
因为有|I1-{1}|>|I-{1}|,而|I-{1}|是I’。大家看我们在上面已经证明了I’是一个最优解了。而I1-{1}>I’。这显然是和归纳假设相违背。因此不存在一个I1是问题的最优解。因此I就是原问题的最优解。得证。
故贪心策略是正确的
下面我们对代码进行分析:
这个也是先排序,然后如果箱子的重量小于等于最大负载量,就把这个箱子加进去,然后负载量就要减去这个箱子的重量。
下面直接上代码
public class Commodity {
int index; //货物编号
int weight; //货物重量
public Commodity() {
// TODO Auto-generated constructor stub
}
public Commodity(int index, int weight) {
super();
this.index = index;
this.weight = weight;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Commodity commodity[]=new Commodity[10];
commodity[0]=new Commodity(1, 2);
commodity[1]=new Commodity(2, 8);
commodity[2]=new Commodity(3,