题 目 贪心算法–最优装载问题 (c++)
学 院 信息工程学院
年级专业
班 级
学 号
姓 名
指导教师
目录
第1章问题描述
1.1问题描述
有一批集装箱要装上一艘载重量为c的轮船。其中集装箱i的重量为Wi 。最优装载问题要求确定在装载体积不受限制的情况下,将尽可能多的集装箱装上轮船。
该问题可形式化描述为:
图1-1可形式化描述
其中,变量Xi=0表示不装入集装箱i,Xi=1表示装入集装箱i
1.2数字实例
重量c=10,集装箱数量n=4,集装箱重量wi=4,3,5,2
表1-1 未排序图表
因为最优装载问题使用最轻者先装,所以按照重量大小排序
表1-2 排序图表
第2章算法思想及算法设计分析
2.1基本思想
在求解过程中,依据某种贪心标准,从问题的初始状态出发,直接去求每一步的最优解,通过若干次的贪心选择,最终得出整个问题的最优解。
贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。
贪心算法不是对所有问题都能得到整体最优解,但对许多问题它都能产生整体最优解或者整体最优解的近似解
2.2贪心算法原理
贪心算法就是做出一系列选择来使原问题达到最优解。在每一个决策点,都是做出当前看来的最优选择,比如在活动选择问题里面,我们总是在一个问题的基础上选择结束时间最早的活动,之后再在剩下活动的基础上选出结束时间最早的活动,以此类推,直到没有活动可以进行选择。但是遗憾的是这种算法并不是总能得到最优解,并且是否能得到最优解还取决于对于贪心策略的选择。
2.3贪心算法基本要素
贪心选择性质:所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择
最优子结构性质:当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质
2.4贪心算法求解的三个步骤
(1)确定贪心策略
(2)根据贪心策略,一步一步得到局部最优解
(3)将局部最优解合并起来就得到全局最优解
2.5使用贪心算法解决最优装载问题
(1)贪心策略:
在所有集装箱里面每次选择重量最小的
(2)局部最优解
根据贪心策略,一步一步地得到局部最优解。例如,第一次选择一个重量最小的集装箱为a1,第二次再从剩下的集装箱中选择一个最小的集装箱,记为a2,以此类推。
(3)把所有的局部最优解合成为原来问题的一个最优解(a1,a2,…)
2.6解题思路
(1)当载重量为c=10时,wi越小时,可装载的集装箱数量n就越大,只有依次选择最小重量的集装箱,直到不能再装为止。
(2)把n个集装箱的重量从小到大排序,然后根据贪心策略尽可能多地选择前i个集装箱,直到不能继续装为止,此时达到最优。
表2-1排序图表
按照贪心的策略,每次选择重量最小的装入
i=0,选择排序后的第1个,装入重量w[i]=2,不超过载重量c,n=1
i=1,选择排序后的第2个,装入重量w[i]=2+3,不超过载重量c,n=2
i=2,选择排序后的第3个,装入重量w[i]=2+3+4,不超过载重量c,n=3
i=3,选择排序后的第4个,装入重量w[i]=2+3+4+5,超过载重量c,算计结束
2.7系统流程图
图2-1系统流程图
第3章程序编码与复杂性分析
3.1编码实现
#include<iostream>
#include "algorithm"
using namespace std;
int main() {
int n;//定义集装箱个数
double c;//定义船的最大承载量
cout << "输入船的最大承载量以及集装箱个数" << endl;
cin >> c >> n;
cout << "输入每件集装箱的重量,用空格分开" << endl;
double * w =new double[n];//用数组填装集装箱的个数
for (int i = 0; i < n; i++) {
cin >> w[i];
}
//冒泡排序
for (int i = n - 1; i > 0; i--)
{
for (int j = 0; j < i; j++) {
if (w[j] > w[j + 1]) {
int temp = w[j];
w[j] = w[j + 1];
w[j + 1] = temp;
}
}
}
double temp = 0.0;//中间值(相当于一个集装箱装进去,然后将集装箱装到船上)
int count = 0;//计数器
for (int i = 0; i < n; i++) {
temp += w[i];
if (temp <= c) {
count++;
}
else {
break;
}
}
cout << "最多可装下" << count << endl;
return 0;
}
3.2 编码优化
将冒泡排序优化为sort方法快速排序
sort(w, w + n);//将集装箱的重量由小到大进行排序
3.3算法复杂度分析
时间复杂度: 首先按照物品体积进行排序,调用sort() 函数,其最优时间复杂度为O(n),最差时间复杂度为 O(n logn),平均时间复杂度为O(n logn), 其中按照 贪心策略寻找最优解的 for 语句的时间复杂度为均为 O(n),因此时间复杂度为 O(n+nlogn)。
第4章测试结果
4.1出错问题及解决方案:
图4-1 错误代码
编译工具报错表达式中必须含有常量值
错误原因:
c++中不允许使用变量作为数组的长度定义数组,必须为常量值,c++中所有的内存需求都是在程序执行前通过定义的常量来确定的。
解决办法:使用关键字new
解决代码:double * w =new double[n];//用数组填装集装箱的个数。
图4-2 解决问题后代码
再次测试:
结果:正常运行
第5章课程设计心得体会
经过一周的课程设计,对贪心算法的解题步骤,以及贪心算法的特点都有了深刻的理解,对语言的理解页更加深入,从刚开始的毫无头绪到最后的有了一点点思路,一边查阅资料,一边翻阅书籍,最后才一点点的做出课程设计,经过这次课程设计,明白了自己对贪心算法理解不够准确,语言基础薄弱,要更加巩固这方面知识
第6章参考文献
王晓东,算法设计与分析(第四版),北京:清华大学出版社,2018