算法分析第五次讨论马上就要到了,我搜索了一下讨论的第一道题目,发现竟然没有详细的解释,我就知道我的机会来了,这下要你们这些喜欢上网搜答案的小崽子们尝尝我的厉害。
开个玩笑,还是开始传教吧。
翻了一下习题解答,它说见主教材第5章的装载问题。
......喵喵喵,裤子都脱了,你就给我看这个?
说实话其实这个还是有用的,第五章就讲了两艘船的装载问题,他用的是回溯法,因为贪心算法已经不能得到问题的最优解了,所以选择用回溯法来做。其实第五章的问题已经发生了稍许变化,它的要求变成了,是否有一个合理的装载方案,将这n个集装箱装上这2艘船。但我们这个题目说的是将一艘推广到两艘,所以我们就根据一艘的要求来做。一艘的要求是装尽可能多的箱子。
那为什么最优装载问题的贪心算法,不能推广到两艘船的情形?
因为两艘船的装载问题,是先装完第一艘,再装第二艘,所以就必须把第一艘尽可能的装满,才能使总的装载量更多。如果使用贪心算法求解,第一艘船装载的方式只可能有一种最优解,就是装载的物品都是以从轻到重的顺序装载,所能装的最大重量,那么问题就来了,从轻到重这样装,不一定是最满的。比如{10,20},c1=20,根据贪心算法,它首先装个10上去,然后,就没然后了,就这样结束了,所以它就没有满足尽可能的装满这一条件 。
#include #include using namespace std; void Loading(int x[], int w[], int c, int n){ sort(w,w+n); for(int i=1;i<=n;i++) x[i]=0; for(int i=0;i<=n&&w[i]<=c;i++){ x[i] = 1; c-=w[i]; } } void Loading2(int x[], int w[], int c1, int c2, int n){ sort(w,w+n); for(int i=1;i<=n;i++) x[i]=0; int i; for(i=0;i<=n&&w[i]<=c1;i++){ x[i] = 1; c1-=w[i]; } for(;i
如上面的代码,6个元素的数组{30,30,30,50,50,60},容量 C1=100,C2=150.箱子总重量为250,轮船的总容量也为250,按理说最优解应该是所有的箱子都能装上船,
但如果使用贪心算法,会先把30,30,30装到第一艘船,就造成了,10个空间的浪费,导致,会有一个箱子不能装上船。
这也算是反例证明了吧。
为什么要先装第一艘,再装第二艘?
为什么要把第一艘船尽可能的装满?
1,是不是有人想说,怎么不两艘轮流着装,我请你吃个棒槌,你见过轮船轮着装集装箱么?就算你不怕麻烦,两艘轮着装,造成的容量浪费可能更加严重。因为贪心算法是从轻到重,那么最坏的情况就是,下一个要装的集装箱刚好大于轮船的剩余容量。如果是一艘船先装,那第一艘的最后一个箱子算中等大小,那第二艘就是终极大小了,比起两艘船一起装所剩的两个终极大箱子的情况要好太多了。加上贪心算法不能推广到两艘船,所以不能用这种方法。
2,先把第一艘船尽可能的装满,是为了第二艘船能放下更多的箱子。
以上纯属个人思考,有误或是写的不好的地方还请指正。
关于两艘船的最优装载问题的回溯法怎么做,这里就先不说了,因为我也不会。