装载问题(2) --课本实现
2016-07-22 10:12
281 查看
书中的实现思路:
首先书中提出的思想:
如果一个给定的装载问题有解,在采用下面的策略一定可以得到最优的装载方案:
(1)首先将一艘轮船尽可能的装满
(2)然后将剩余的集装箱装上第二艘轮船
根据上述的思想,书中代码实现如下:
实现1:只是单纯的求出c1号仓库最优的装载重量
实现2:在 实现1 的基础上增加了剪枝函数
增加剪枝函数的实现思想:如果r代表的剩余的没有装的物品的总量,如果r+cw <= bestw ;那么就没有必要再往下面遍历了,于是书中就说可将当前节点Z的右子树减掉去。(其实我一直想为什么不把左子树一起剪去呢?
)
代码:
实现3 在实现2的基础上 构造最优解
为了构造最优解,必须在算法中记录与当前最优值相应的当前的最优解。其实也就是使用x[i]记录从根到当前节点的路径; best[i]记录当前最优解
代码:
首先书中提出的思想:
如果一个给定的装载问题有解,在采用下面的策略一定可以得到最优的装载方案:
(1)首先将一艘轮船尽可能的装满
(2)然后将剩余的集装箱装上第二艘轮船
根据上述的思想,书中代码实现如下:
实现1:只是单纯的求出c1号仓库最优的装载重量
/* *出发点是问题一定有解(算法中没考虑无解的情形) */ #include<stdio.h> int n = 3;//物品的数量 int w[4] = {0,40,40,10}; //存放物品的重量,w[0] 不使用 int c1 = 50; //第一个箱子的容量 int c2 = 50; //第二个箱子的容量 int bestw; //记录当前得到的最优的装载重量 int cw; //当前得到的装载重量 void Backtrack(int i); int main(){ Backtrack(1); } void Backtrack(int i){ if (i > n){ //写递归函数,注意首先一定要考虑递归结束的条件 if (cw > bestw){ bestw = cw; printf("%d ",bestw); //最后一次打印出的bestw为最优的装载重量 } return; } if (cw + w[i] <= c1){ //注意这里不要少了等号!! cw = cw + w[i]; Backtrack(i+1); cw = cw - w[i]; //这一步是考虑不装当前的货物w[i],即往当前节点的右子树遍历的时候的情况 } Backtrack(i+1); }
实现2:在 实现1 的基础上增加了剪枝函数
增加剪枝函数的实现思想:如果r代表的剩余的没有装的物品的总量,如果r+cw <= bestw ;那么就没有必要再往下面遍历了,于是书中就说可将当前节点Z的右子树减掉去。(其实我一直想为什么不把左子树一起剪去呢?
)
代码:
/* *书中的出发点是问题一定有解(算法中没考虑无解的情形) */ //下面求出c1号仓库最优的装载重量+增加了剪枝函数 #include<stdio.h> int n = 3;//物品的数量 int w[4] = {0,40,40,10}; //存放物品的重量,w[0] 不使用 int c1 = 50; //第一个箱子的容量 int c2 = 50; //第二个箱子的容量 int bestw; //记录当前得到的最优的装载重量 int cw; //当前得到的装载重量 int r; //记录当前剩余的重量 void Backtrack(int i); int main(){ for (int i=1;i<=n; i++){ r += w[i]; } Backtrack(1); } void Backtrack(int i){ if (i > n){ //写递归函数,注意首先一定要考虑递归结束的条件 //if (cw > bestw){ 既然增加了剪枝函数,这里的判断就变得多余了 bestw = cw; printf("%d ",bestw); //最后一次打印出的bestw为最优的装载重量 //} return; } r = r - w[i]; if (cw + w[i] <= c1){ //注意这里不要少了等号!! cw = cw + w[i]; Backtrack(i+1); cw = cw - w[i]; //这一步是考虑不装当前的货物w[i],即往当前节点的右子树遍历的时候的情况 } if (cw + r > bestw){ //剪枝函数 Backtrack(i+1); } r += w[i]; }
实现3 在实现2的基础上 构造最优解
为了构造最优解,必须在算法中记录与当前最优值相应的当前的最优解。其实也就是使用x[i]记录从根到当前节点的路径; best[i]记录当前最优解
代码:
/* *书中的出发点是问题一定有解(算法中没考虑无解的情形) */ //下面只是单纯的求出c1号仓库最优的装载重量 #include<stdio.h> int n = 3;//物品的数量 int w[4] = {0,40,40,10}; //存放物品的重量,w[0] 不使用 int c1 = 50; //第一个箱子的容量 int c2 = 50; //第二个箱子的容量 int bestw; //记录当前得到的最优的装载重量 int cw; //当前得到的装载重量 int r; //记录当前剩余的重量 int x[4]; int bestx[4]; void Backtrack(int i); int main(){ for (int i=1;i<=n; i++){ r += w[i]; } Backtrack(1); printf("%d \n",bestw); for (int i=1; i<=n; i++){ printf("%d", bestx[i]); } } void Backtrack(int i){ if (i > n){ //写递归函数,注意首先一定要考虑递归结束的条件 bestw = cw; for (int i=1; i<=n; i++){ bestx[i] = x[i]; } return; } r = r - w[i]; if (cw + w[i] <= c1){ //注意这里不要少了等号!! x[i] = 1; //装入1号箱子 cw = cw + w[i]; Backtrack(i+1); cw = cw - w[i]; //这一步是考虑不装当前的货物w[i],即往当前节点的右子树遍历的时候的情况 } if (cw + r > bestw){ //剪枝函数 x[i] = 0; //不装入1号箱子 Backtrack(i+1); } r += w[i]; }代码4:迭代回溯(抽空补上)
相关文章推荐
- 书评:《算法之美( Algorithms to Live By )》
- 动易2006序列号破解算法公布
- C#递归算法之分而治之策略
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- C#算法之大牛生小牛的问题高效解决方法
- C#算法函数:获取一个字符串中的最大长度的数字
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C#实现的算24点游戏算法实例分析
- 经典排序算法之冒泡排序(Bubble sort)代码
- c语言实现的带通配符匹配算法
- 浅析STL中的常用算法
- 算法之排列算法与组合算法详解
- C++实现一维向量旋转算法
- Ruby实现的合并排序算法
- C#折半插入排序算法实现方法