算法分析第五次讨论马上就要到了,我搜索了一下讨论的第一道题目,发现竟然没有详细的解释,没有办法只能自己写了。
翻了一下习题解答,它说见主教材第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<n&&w[i]<=c2;i++){
x[i] = 1;
c2 -= w[i];
}
}
int main(){
int n=5;
int c=40;
int w[5]={10,40,40,80,100};
int x[n];
Loading(x,w,c,n);
cout<<"\n一艘船的装载问题:\n";
for(int i=0;i<n;i++){
cout<<x[i]<<"\t";
}
int c1=100;
int c2=150;
int v[6]={30,30,30,50,50,60};
int y[n];
Loading2(y,w,c1,c2,n);
cout<<"\n两艘船的装载问题:\n";
for(int i=0;i<n;i++){
cout<<y[i]<<"\t";
}
return 0;
}
如上面的代码,6个元素的数组{30,30,30,50,50,60},容量 C1=100,C2=150.箱子总重量为250,轮船的总容量也为250,按理说最优解应该是所有的箱子都能装上船,
但如果使用贪心算法,会先把30,30,30装到第一艘船,就造成了,10个空间的浪费,导致,会有一个箱子不能装上船。
这也算是反例证明了吧。
而回溯法因为考虑到了所有的装载顺序,所以一定能找到最优的装载方案。
1. 为什么要先装第一艘,再装第二艘?
是不是有人想会,怎么不两艘轮流着装,我请你吃个棒槌,你见过轮船轮着装集装箱么?就算你不怕麻烦,两艘轮着装,造成的容量浪费可能更加严重。因为贪心算法是从轻到重,那么最坏的情况就是,下一个要装的集装箱刚好大于轮船的剩余容量。如果是一艘船先装,那第一艘的最后一个箱子算中等大小,那第二艘就是终极大小了,比起两艘船一起装所剩的两个终极大箱子的情况要好太多了。加上贪心算法不能推广到两艘船,所以不能用这种方法。
2. 为什么要把第一艘船尽可能的装满?
先把第一艘船尽可能的装满,是为了第二艘船能放下更多的箱子。
关于两艘船的最优装载问题的回溯法,懒得写了,两种算法的实际对比效果,还是想想得了。
以上纯属个人思考。
有不同想法的,欢迎一起讨论。
—————————————————————————————————————————
再次回顾了一下,发现一些问题:
一艘船的情况下,最优装载能产生最优解?。。。可能没看题目,已经不知道说的是什么了,貌似说的是尽可能多装几个箱子,那还行,一艘船的情况下,从小装到大,装的箱子肯定是最多的,常识常识。但两艘船的情况下,如果使用最优装载,可能会浪费一些空间,导致装得箱子的数量没有回溯法装得那么多。
一句话解决的事情,不知道前面说了那么多废话是干嘛的 = =
前不久参加2018华为的软挑比赛,发现一个很现实的问题,在实际中其实不管使用最优装载还是回溯法或者是01背包,它们的总利用率都是差不多的,因为即使第一艘装得很满了,第二艘少装一点,但仍然需要使用两艘船。甚至可能出现,第一艘非常满,而第二艘,只装了一点的尴尬情况。
要体现出算法优化的效果,我觉得只有当数据量非常大的时候,积少成多,就可能少用几艘船,比如说,有一批货物和若干艘艘船,每艘船能装载的重量为30,假如每艘船使用回溯能比最优装载,多装下 2 的货物,则15艘船才能省下一艘船的开销。但这也只是假想情况,实际处理的时候,还是有很多的不确定性,比如说能省下的空间可能只占0.01%,或者最优装载得到结果本来就是最优了。并且数据量大了,算法的性能会变得很差。