第1关:装载问题 (FIFO 优先队列法)

问题描述

有一批共个集装箱要装上 2 艘载重量分别为 C1 和 C2 的轮船,其中集 装箱 i 的重量为 Wi ,且

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

容易证明:如果一个给定装载问题有解,则采用下面的策略可得到最优装载方案。

(1)首先将第一艘轮船尽可能装满;

(2)将剩余的集装箱装上第二艘轮船。

任务描述

本关任务:采用队列式分支限界法来完成装载问题

相关知识

在算法的 while 循环中,首先检测当前扩展结点的左儿子结点是否为可行结点。如果是则将其加入到活结点队列中。然后将其右儿子结点加入到活结点队列中(右儿子结点一定是可行结点)。 2 个儿子结点都产生后,当前扩展结点被舍弃。 活结点队列中的队首元素被取出作为当前扩展结点,由于队列中每一层结点之后都有一个尾部标记 -1 ,故在取队首元素时,活结点队列一定不空。当取出的元素是 -1 时,再判断当前队列是否为空。如果队列非空,则将尾部标记 -1 加入活结点队列,算法开始处理下一层的活结点。

  1. while (true) {
  2. // 检查左儿子结点
  3. if (Ew + w[i] <= c) // x[i] = 1
  4. EnQueue(Q, Ew + w[i], bestw, i, n);
  5. // 右儿子结点总是可行的
  6. EnQueue(Q, Ew, bestw, i, n); // x[i] = 0
  7. Q.Delete(Ew); // 取下一扩展结点
  8. if (Ew == -1) { // 同层结点尾部
  9. if (Q.IsEmpty()) return bestw;
  10. Q.Add(-1); // 同层结点尾部标志
  11. Q.Delete(Ew); // 取下一扩展结点
  12. i++;} // 进入下一层 } }

算法改进

节点的左子树表示将此集装箱装上船,右子树表示不将此集装箱装上船。设 bestw 是当前最优解; ew 是当前扩展结点所相应的重量; r 是剩余集装箱的重量。则当 ew+rbestw 时,可将其右子树剪去,因为此时若要船装最多集装箱,就应该把此箱装上船。

另外,为了确保右子树成功剪枝,应该在算法每一次进入左子树的时候更新 bestw 的值。

  1. // 检查左儿子结点
  2. Type wt = Ew + w[i]; // 左儿子结点的重量
  3. if (wt <= c) { // 可行结点
  4. if (wt > bestw) bestw = wt;
  5. // 加入活结点队列
  6. if (i < n) Q.Add(wt);
  1. //检查右儿子结点
  2. if (Ew + r > bestw && i < n)
  3. Q.Add(Ew); // 可能含最优解
  4. Q.Delete(Ew); // 取下一扩展结点

构造最优解

为了在算法结束后能方便地构造出与最优值相应的最优解,算法必须存储相应子集树中从活结点到根结点的路径。为此目的,可在每个结点处设置指向其父结点的指针,并设置左、右儿子标志。

  1. class QNode
  2. {QNode *parent; // 指向父结点的指针
  3. bool LChild; // 左儿子标志
  4. Type weight; // 结点所相应的载重量

编程要求

请仔细阅读右侧代码,结合相关知识,在 Begin - End 区域内进行代码补充,完成使用队列式分支限界法来完成装载问题的任务。

测试说明

平台会对你编写的代码进行测试:

测试输入: 4 70 20 10 26 15

预期输出: Ship load:70

The weight of the goods to be loaded is:

20 10 26 15

Result: 1 0 1 1

The optimal loading weight is:61

开始你的任务吧,祝你成功!

参考代码:

//装载问题 队列式分支限界法求解 #include "Queue.h"
#include <iostream>
using namespace std;int N = 0;template<class Type>
class QNode
{public:QNode *parent;  //指向父节点的指针bool LChild;    //左儿子标识Type weight;    //节点所相应的载重量
};template<class Type>
void EnQueue(Queue<QNode<Type>*>&Q,Type wt,int i,int n,Type bestw,QNode<Type>*E,QNode<Type> *&bestE,int bestx[],bool ch);template<class Type>
Type MaxLoading(Type w[],Type c,int n,int bestx[]);int main()
{float c = 0;  float w[100] = {0};//下标从1开始  int x[100];  float bestw;cin>>N;cin >>c;for(int i=1; i<=N; i++)  {  cin>>w[i];  }  cout<<"Ship load:"<<c<<endl;  cout<<"The weight of the goods to be loaded is:"<<endl;  for(int i=1; i<=N; i++)  {  cout<<w[i]<<" ";  }  cout<<endl;  bestw = MaxLoading(w,c,N,x);  cout<<"Result:"<<endl;  for(int i=1; i<=N; i++)  {  cout<<x[i]<<" ";  }  cout<<endl;  cout<<"The optimal loading weight is:"<<bestw<<endl;return 0;
}//将活节点加入到活节点队列Q中
template<class Type>
void EnQueue(Queue<QNode<Type>*>&Q,Type wt,int i,int n,Type bestw,QNode<Type>*E,QNode<Type> *&bestE,int bestx[],bool ch)
{if(i == n)//可行叶节点{if(wt == bestw){//当前最优装载重量bestE = E;bestx[n] = ch;         }return;}//非叶节点QNode<Type> *b;b = new QNode<Type>;b->weight = wt;b->parent = E;b->LChild = ch;Q.Add(b);
}template<class Type>
Type MaxLoading(Type w[],Type c,int n,int bestx[])
{//队列式分支限界法,返回最优装载重量,bestx返回最优解//初始化Queue<QNode<Type>*> Q;        //活节点队列Q.Add(0);                    //同层节点尾部标识int i = 1;                   //当前扩展节点所处的层Type Ew = 0,               //扩展节点所相应的载重量bestw = 0,                //当前最优装载重量r = 0;                   //剩余集装箱重量for(int j=2; j<=n; j++){r += w[j];}QNode<Type> *E = 0,         //当前扩展节点*bestE;         //当前最优扩展节点//搜索子集空间树//**************begin************/while(true){//检查左儿子节点Type wt = Ew + w[i];if(wt <= c)//可行节点{if(wt>bestw){bestw = wt;}EnQueue(Q,wt,i,n,bestw,E,bestE,bestx,true);}//检查右儿子节点if(Ew+r>bestw){EnQueue(Q,Ew,i,n,bestw,E,bestE,bestx,false);}Q.Delete(E);//取下一扩展节点if(!E)//同层节点尾部{if(Q.IsEmpty()){break;}Q.Add(0);       //同层节点尾部标识Q.Delete(E);    //取下一扩展节点i++;            //进入下一层r-=w[i];        //剩余集装箱重量}Ew  =E->weight;        //新扩展节点所对应的载重量}//**************end**************///构造当前最优解//**************begin************/for(int j = n - 1; j > 0; --j){bestx[j] = bestE->LChild;bestE = bestE->parent;}//**************end**************/return bestw;
}

第2关:装载问题 (最优队列法)

问题描述

有一批共个集装箱要装上 2 艘载重量分别为 C1 和 C2 的轮船,其中集 装箱i的重量为 Wi ,且

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

容易证明:如果一个给定装载问题有解,则采用下面的策略可得到最优装载方案。

(1)首先将第一艘轮船尽可能装满;

(2)将剩余的集装箱装上第二艘轮船。

任务描述

本关任务:采用优先队列式分支限界法来完成装载问题

相关知识

  1. 解装载问题的优先队列式分支限界法用最大优先队列存储活结点表活结点 x 在优先队列中的优先级定义为从根结点到结点x的路径所相应的载重量再加上剩余集装箱的重量之和。

  2. 优先队列中优先级最大的活结点成为下一个扩展结点。以结点 x 为根的子树中所有结点相应的路径的载重量不超过它的优先级。子集树中叶结点所相应的载重量与其优先级相同。

  3. 在优先队列式分支限界法中,一旦有一个叶结点成为当前扩展结点,则可以断言该叶结点所相应的解即为最优解。此时可终止算法。

编程要求

请仔细阅读右侧代码,结合相关知识,在 Begin - End 区域内进行代码补充,完成采用优先队列式分支限界法来完成装载问题的任务。

测试说明

平台会对你编写的代码进行测试:

测试输入: 4 70 20 10 26 15

预期输出: Ship load:70 The weight of the goods to be loaded is: 20 10 26 15 Result: 1 0 1 1 The optimal loading weight is:61

开始你的任务吧,祝你成功!

 参考代码:

//装载问题 优先队列式分支限界法求解
#include "MaxHeap.h"int N;class bbnode;template<class Type>
class HeapNode
{public:operator Type() const{return uweight;}bbnode *ptr;      //指向活节点在子集树中相应节点的指针Type uweight;        //活节点优先级(上界)int level;          //活节点在子集树中所处的层序号
};class bbnode
{template<class Type>friend void AddLiveNode(MaxHeap<HeapNode<Type>>& H,bbnode *E,Type wt,bool ch,int lev);template<class Type>friend Type MaxLoading(Type w[],Type c,int n,int bestx[]);friend class AdjacencyGraph;private:bbnode *parent;        //指向父节点的指针bool LChild;      //左儿子节点标识
};template<class Type>
void AddLiveNode(MaxHeap<HeapNode<Type>>& H,bbnode *E,Type wt,bool ch,int lev);template<class Type>
Type MaxLoading(Type w[],Type c,int n,int bestx[]);int main()
{float c = 0;  float w[100] = {0};//下标从1开始  int x[100];  float bestw;cin>>N;cin >>c;for(int i=1; i<=N; i++)  {  cin>>w[i];  }  cout<<"Ship load:"<<c<<endl;  cout<<"The weight of the goods to be loaded is:"<<endl;  for(int i=1; i<=N; i++)  {  cout<<w[i]<<" ";  }  cout<<endl;  bestw = MaxLoading(w,c,N,x);  cout<<"Result:"<<endl; for(int i=1; i<=N; i++)  {  cout<<x[i]<<" ";  }  cout<<endl;  cout<<"The optimal loading weight is:"<<bestw<<endl;return 0;
}//将活节点加入到表示活节点优先队列的最大堆H中
template<class Type>
void AddLiveNode(MaxHeap<HeapNode<Type>>& H,bbnode *E,Type wt,bool ch,int lev)
{bbnode *b = new bbnode;b->parent = E;b->LChild = ch;HeapNode<Type> N;N.uweight = wt;N.level = lev;N.ptr = b;H.Insert(N);
}//优先队列式分支限界法,返回最优载重量,bestx返回最优解
template<class Type>
Type MaxLoading(Type w[],Type c,int n,int bestx[])
{//定义最大的容量为1000MaxHeap<HeapNode<Type>> H(1000);//定义剩余容量数组Type *r = new Type[n+1];r[n] = 0;//**************begin************/for(int j=n-1; j>0; j--){r[j] = r[j+1] + w[j+1];}//**************end**************///初始化int i = 1;//当前扩展节点所处的层bbnode *E = 0;//当前扩展节点Type Ew = 0; //扩展节点所相应的载重量//搜索子集空间树//**************begin************/while(i!=n+1)//非叶子节点{//检查当前扩展节点的儿子节点if(Ew+w[i]<=c){AddLiveNode(H,E,Ew+w[i]+r[i],true,i+1);}//右儿子节点AddLiveNode(H,E,Ew+r[i],false,i+1);//取下一扩展节点HeapNode<Type> N;H.DeleteMax(N);//非空i = N.level;E = N.ptr;Ew = N.uweight - r[i-1];}//**************end**************///构造当前最优解//**************begin************/for(int j=n; j>0; j--){bestx[j] = E->LChild;E = E->parent;}//**************end**************/return Ew;
}

关于接下来的实验内容,我也会在【WRITE-BUG】技术平台更新,也可以为大家带来更好的观感,带来更多的分享,欢迎大家前来浏览。

算法设计与分析—分支限界法应用(头歌实验)相关推荐

  1. AlphaBeta剪枝算法求解博弈树最优选择 头歌实验平台

    AlphaBeta剪枝算法求解博弈树最优选择 头歌实验平台 前言 一.AlphaBeta剪枝是什么? 1.由来, 最大最小决策树 2.发展 3. AlphaBeta剪枝 二.实验算法伪代码 三.实验算 ...

  2. 算法设计与分析——分支限界法——n皇后问题

    一.问题描述 问题描述:在nn格的棋盘上放置彼此不受攻击的n个皇后.按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子.n皇后问题等价于在n*n的棋盘上放置n个皇后,任何2个皇后 ...

  3. 算法设计与分析——分支限界法

    文章目录 1. 分支界限法 1.1 基本思想 1.2 搜索策略 1.3 队列式 1.4* 优先队列式 2. 典型案例 2.1 装载问题 2.1.1 问题描述 2.1.2 约束函数和限界条件 2.1.3 ...

  4. 算法设计与分析-分支限界法习题

    7-1 布线问题 印刷电路板将布线区域划分成 n×m 个方格阵列,要求确定连接方格阵列中的方格a 点到方格b 的最短布线方案.在布线时,电路只能沿直线布线,为了避免线路相交,已布了线的方格做了封锁标记 ...

  5. 算法设计与分析——分支限界法——装载问题

    有一批共个集装箱要装上2艘载重量分别为C1和C2的轮船,其中集装箱i的重量为Wi,且装载问题要求确定是否有一个合理的装载方案可将这个集装箱装上这2艘轮船.如果有,找出一种装载方案. 容易证明:如果一个 ...

  6. 算法设计与分析之分支限界法

    文章目录 前言 一.分支限界法概述 二.分支限界法的基本思想 三.分支限界法的基本过程 四.常见的两种分支限界法 五.应用分支限界法应注意的关键问题 六.分支限界法示例 总结 前言 大家好,越努力,越 ...

  7. 循环赛日程表非递归Java_王晓东《算法设计与分析》课件.ppt

    <王晓东<算法设计与分析>课件.ppt>由会员分享,可在线阅读,更多相关<王晓东<算法设计与分析>课件.ppt(356页珍藏版)>请在人人文库网上搜索. ...

  8. 算法设计与分析第七章分支限界算法(完结篇)

    算法设计与分析第七章分支限界算法 一.分支界限算法概述 1.分支限界法类似于回溯法,是一种在问题的解空间树上搜索问题解的算法. 分支限界法的求解目标则是找出满足约束条件的一个解,或是在满足约束条件的解 ...

  9. 算法设计与分析--期末复习重点总结

    目录 一.算法概述 1.算法的定义与特性 2.数学证明法 3.算法复杂性分析方法 4.渐进分析 二.递归与分治策略 1.递归概念 2.递归算法设计示例 3.递归算法分析 4.分治基本思想 5.分治算法 ...

最新文章

  1. VMware虚拟化--ESXi安装时考虑因素
  2. tableau实战系列(九)-用 ZN 函数处理数据缺失点
  3. Java基础 五 方法
  4. QPW 企业员工表(tf_company_employee)
  5. Educational Codeforces Round 20 B. Distances to Zero
  6. 【EMC】电压暂降、短时中断和电压变化
  7. apqp过程流程图范本_过程流程图(APQP要求)
  8. 微信公众号支付流程解读及支付签名验证方法
  9. PythonTutor本地化运行
  10. 静态HTML网页设计作品——动漫电影《你的名字》(7页) HTML+CSS大作业_ 动漫电网页制作作业_动漫电网页设计...
  11. Word文档如何在方框里打勾?三招让你从入门到精通,工作效率翻倍
  12. 三十六计之借刀杀人(第三计)
  13. Python爬虫实战,拉黑 QQ 空间屏蔽我的“大人物“
  14. 虚拟硬盘 服务器 破解,服务器版虚拟硬盘_Primo Ramdisk Server Edition V5.6.1 免费版
  15. 泊松分布 (Poisson-Disc)算法
  16. 常见的四种回归测试分析
  17. 分解质因数分 (10分)
  18. jitter单位_Jitter知识
  19. 英特尔至强融核助力国家海洋局探索超算应用
  20. 软件工程之面向对象分析与设计

热门文章

  1. ffmpeg实现视频和音频分离,并且将声音切片
  2. pythonurllib新浪微博_Python代码登录新浪微博并自动发微博
  3. 记一次内网SSH后门误报事件
  4. strstr函数实现(C语言)
  5. 2021秋软工实践个人作业一
  6. STM32+二氧化碳传感器(FS00301)
  7. 南邮 OJ 1076 机器狗组装费用
  8. 导入excel时报错The supplied data appears to be in the Office 2007+ XML.
  9. Edge兼容IE,Edge关闭弹窗阻止
  10. 川土微电子产品在PLC/伺服领域的应用