参考:https://blog.csdn.net/m0_38015368/article/details/80196634

问题描述:

有n个集装箱要装上2艘载重量分别为c1和c2的轮船,其中集装箱i的重量为wi,且

问是否有一个合理的装载方案,可将这n个集装箱装上这2艘轮船。如果有,找出一种装载方案。

问题分析:

如果一个给定装载问题有解,则采用下面的策略可得到最优装载方案。
(1)首先将第一艘轮船尽可能装满;
(2)将剩余的集装箱装上第二艘轮船。

将第一艘轮船尽可能装满等价于选取全体集装箱的一个子集,使该子集中集装箱重量之和最接近c1。由此可知,装载问题等价于以下特殊的0-1背包问题:

      且    

算法思路:

子集树表示解空间,则解为n元向量{x1,  ... ,xn }, xi∈{0, 1} 。

约束函数:

当前搜索的层i <= n时,当前扩展结点Z为子集树的内部结点,对于当前扩展结点,其右子树约束函数值与其父节点相同,则仅当满足cw+w[i] <= c时进入左子树,x[i]=1; 当cw+w[i] > c ,在以结点Z为根的子树中所有结点都不满足约束条件,因而该子树中解都是不可行解,因而将在该子树删去。

限界函数:

由于是最优化问题, 可利用最优解性质进一步剪去不含最优解的子树:
设Z是解空间树第i层上的当前扩展结点。
设           bestw:  当前最优载重量, 
                   cw:  当前扩展结点Z的载重量 ; 
                      r:  剩余集装箱的重量;
在以Z为根的子树中任意叶结点所相应的载重量不超过cw + r。因此,对于当前扩展结点,其左子树限界函数值与其父节点相同,则仅当cw + r  ≤ bestw时,可将Z的右子树剪去。
即:cw +  r > bestw 时搜索右子树,x[i]=0;

#include <iostream>
#include <cstring>using namespace std;int n;                  //集装箱数
int bw = 0;                //best_weight:当前最优载重量(已搜索的解空间树中)
int cw = 0;                //current_weight:当前载重量(从根结点到当前结点部分解)
int x[100];             //当前向量
int bestx[100];         //最优解向量
int w[100];             //weight:集装箱重量
int c1;                 //第一艘船最大载重量
int c2;                 //第二艘船最大载重量
int r;                  //rest:剩余集装箱重量void bacctrack(int i)
{//搜索到叶子结点,更新最优解 if(i > n){for(int i = 0; i < n; i++)bestx[i] = x[i];bw = cw;}r -= w[i];/*剪枝 + 搜索右儿子的约束函数值与其父节点相同; 左儿子的限界函数值与其父节点相同;所以在搜索左儿子时,则只需判断约束函数能否将其剪枝 搜索右儿子时,则只需判断限界函数能否将其剪枝 */ //搜索左儿子 if(cw + w[i] <= c1) {x[i] = 1;cw += w[i];bacctrack(i + 1);cw -= w[i];       //回溯到父节点时,cw要更新为: cw - w[i]}//搜索右儿子 if(cw + r > bw){x[i] = 0;bacctrack(i + 1);                  //回溯到父节点时,r要更新为:r + w[i] r += w[i];                        }
} int main()
{cout << "请输入集装箱数量:" << endl; cin >> n;cout << "请输入两艘船最大载重量:" << endl;cin >> c1 >> c2; cout << "请输入集装箱重量:" << endl; for(int i = 1; i <= n; i++)cin >> w[i];//将r初始化为所有集装箱的重量之和,那么当前扩展结点的r = r - w[i],避免每次计算的前结点的cw + r for(int i = 1; i <= n; i++)r += w[i];bacctrack(1);//判断在第一艘船尽可能装满后,剩下的集装箱能否装入第二搜船 int rest_sum = 0;  for(int i = 1; i <= n; i++){if(bestx[i] == 0){rest_sum += w[i];}    }if(rest_sum > c2)cout << "无法装入" << endl;else{cout << "第一艘船装入的货物是:";for(int i = 1; i <= n; i++){if(bestx[i] == 1)cout << i << " ";}cout << endl;cout << "第二艘船装入的货物是:";for(int i = 1; i <= n; i++){if(bestx[i] == 0)cout << i << " ";}cout << endl;}return 0;
}   

测试样例:

(1)

(2)

回溯法求解装载问题(DFS + 剪枝策略)相关推荐

  1. 回溯法 | 求解装载问题

    问题描述: 有 n 个集装箱要装上一艘载重量为 W 的轮船,其中集装箱 i (1<=i<=n) 的重量,为wi.子啊装在体积不受限制的情况下,将尽可能重的集装箱装上轮船,当重量相同时要求选 ...

  2. 使用回溯法求解装载问题

    回溯法解决装载问题(java实现) 问题描述:有n个集装箱要装上两艘载重量分别为C1和C2的轮船,其中集装箱i的重量为wi,且:∑ wi ≤ C1+C2. 求是否有一个合理的装载方案能将这 n 个集装 ...

  3. 回溯法 —— 求解0/1背包问题(剪枝)

    0/1背包问题 题目描述: 有n个重量分别为w1,w2,-,wn的物品(物品编号为1~n),它们的价值分别为v1,v2,-,vn,给定一个容量为W的背包.设计从这些物品中选取一部分物品放入该背包的方案 ...

  4. 【算法分析】实验 4. 回溯法求解0-1背包等问题

    目录 实验内容 实验目的 实验结果 步骤1:描述与分析 步骤2:策略以及数据结构 步骤3 步骤4 步骤5 步骤6 实验总结 实验内容 本实验要求基于算法设计与分析的一般过程(即待求解问题的描述.算法设 ...

  5. 算法设计与分析 实验三 回溯法求解地图填色问题

    回溯法求解地图填色问题 一.实验目的与要求 1.实验基本要求: 2.实验亮点: 二.实验内容与方法 三.实验步骤与过程 1.未优化的回溯: (1)算法描述: (2)编程实现 (3)运行并测试: 2.对 ...

  6. java背包算法回溯法_【算法分析】实验 4. 回溯法求解0-1背包等问题

    [TOC] 实验内容 本实验要求基于算法设计与分析的一般过程(即待求解问题的描述.算法设计.算法描述.算法正确性证明.算法分析.算法实现与测试),通过回溯法的在实际问题求解实践中,加深理解其基本原理和 ...

  7. 回溯法求解N皇后问题及其时间复杂度分析

    回溯法求解N皇后问题及其时间复杂度分析 一.回溯法简介 1. 什么是回溯法? 2. 回溯法的时间复杂度分析 蒙特卡罗方法 蒙特卡罗方法在回溯法求解时间复杂度中的应用 二.回溯法求解N皇后问题 1. 回 ...

  8. 0027算法笔记——【回溯法】回溯法与装载问题

    1.回溯法 (1)描述:回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标.但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法.  (2)原 ...

  9. 回溯法求解0-1背包问题

    回溯法求解0-1背包问题时比较随机序列和按 v/w 降序排列的算法 问题描述: 针对0-1背包问题,尝试用回溯法. 物品总数N=10,背包容量 C=26, 物品的重量数组为w={7,3,10,12,1 ...

最新文章

  1. SAP有用的NOTE(持续更新)
  2. 【LorMe云讲堂】梁玉婷:农田土壤微生物共存与功能识别调控
  3. eltable 无数据文案修改_有哪些适合十二月发的文艺文案?记录文案用这款图片便签...
  4. 裸奔、抽烟、凡尔赛,原来数学家玩得这么野……
  5. c++ 圆上任意点坐标计算_线性代数总结 第三章 向量代数与几何计算(空间平面和直线)...
  6. 运用范式的规范数据库设计的好处
  7. cuda nvidia安装程序失败_Ubuntu16.04安装nvidia-docker
  8. 中国男性最想娶回家的金庸女性角色排行榜zz
  9. 小技巧|Cadence安装之后,原理图DSN文件的默认图标不对如何进行修改
  10. 如何查看自己windows密钥
  11. python游戏数据分析
  12. java-redis java使用redisTemplate连接操作单台Redis
  13. python绘制等高线图
  14. excel编辑csv文件
  15. 使用tensorboard出现:“couldn‘t build proto file into descriptor pool!”的解决方法
  16. android开发百度地图步行导航
  17. AXURE手机版注册登录原型(下载+教学)
  18. 【观察】中国跨境电商出海再加速背后,如何破解行业同质化竞争困局?
  19. 三星账户联系人同步到手机上_如何将健身数据从Samsung Health同步到Google Fit
  20. Facebook推出Events应用 帮用户找到有趣活动

热门文章

  1. Python模拟订单号生成
  2. 其实,男人也需要被疼爱
  3. matlab中如何输出,MATLAB中如何实现输出一个函数表达式
  4. 巧用img的width和height属性进行缩图,使图片不变形
  5. mysql数据库效率最高_LVS+Keepalived效率最高的群集(实战)
  6. 【python】无规律时间步长时序数据转为固定步长
  7. NLP自然语言处理系列-音乐推荐系统实战 - 数据处理
  8. 手机访问网站 点击手机号码直接拨打电话
  9. DAHUA拼接屏操作步骤
  10. Samba实现Linux与windows文件共享