分支限界算法报告

合集下载

实验六 分支限界法

实验六 分支限界法

算法设计与分析实验报告
学号姓名班级
上课地点教师上课时间
实验六分支限界法
1. 实验目的
1.1.掌握分支限界法的基本思路
1.2.掌握用分支限界法分析和处理货郎担问题和0/1背包问题
2. 实验环境
2.1 Eclipse, VC++
2.2 Window XP
3. 实验内容
3.1 圆排列问题
4. 教师批改意见
成绩
签字:
日期:
实验报告细表
1实验题目
1.1 算法设计思想
可文字描述,适当添加一些伪代码,或者流程图来进行补充说明
1.2 程序源码
1.3 实验结论(结果验证)
要有截图,验证最后结果(图片分布要合理)。

截图要格式参考如下:
输入跟input.txt中一致,按output.txt规格输出。

一般以ns 为单位。

当数字太大时,比如:
可切换成ms为单位。

1.4 心得体会
2实验题目
1.1 算法设计思想
1.2 程序源码
1.3 实验结论(结果验证)
1.4 心得体会。

分支限界法求解装载问题实验报告

分支限界法求解装载问题实验报告
void EnQueue(int wt,int& bestw, int i, int n, Queue*E,Queue*&bestE, bool ch) // 该函数负责加入活结点 { // 如果不是叶结点,则将结点权值 wt 加入队列 Q
if (i == n) {
if(wt == bestw) {
friend Type MaxLoading_three(Type *,Type,int,int *); private:
QNode* parent;// 指向父结点的指针 bool LChild; //左儿子标志 Type weight; //结点所相应的载重量 };
四、算法实现
void EnQueue(int wt,int& bestw, int i, int n, Queue*E,Queue*&bestE, bool ch) // 该函数负责加入活结点 { // 如果不是叶结点,则将结点权值 wt 加入队列 Q
} 构造最优解: 为了在算法结束后能方便地构造出与最优值相应的最优解,算法必须存储相应子集树中从活 结点到根结点的路径。为此目的,可在每个结点处设置指向其父结点e> class QNode {
friend void EnQueue(queue<QNode <Type> * >&,Type,int,int,Type,QNode <Type> *,QNode <Type> * &,int*,bool);
if (IsEmpty()) break; if(i<n) Add(-1, NULL, 0); // 同层结点的尾部 Delete(E); // 取下一扩展结点 i++; // 进入下一层 r -= w[i]; } Ew = E->weight; } //构造当前最优解 for(j = n -1; j>0; j--) { bestx[j] = bestE->LChild; bestE = bestE ->parent; } return 0; }

实验报告分支限界法01背包

实验报告分支限界法01背包

实验报告分支限界法01背包实验报告:分支限界法解决01背包问题一、引言背包问题是数学和计算机科学中一个经典的问题。

背包问题通常分为01背包问题和完全背包问题两种情况。

本实验主要探讨的是分支限界法解决01背包问题,该算法常用于解决NP难问题。

分支限界法通过将问题分解为一系列子问题,并借助剪枝技术,逐步缩小问题的空间,从而找到最优解。

本实验将通过具体的案例来展示分支限界法的求解过程和原理,并对算法的时间复杂度和空间复杂度进行分析。

二、算法原理01背包问题的数学模型为:有n个物品,每个物品有一个重量wi和一个价值vi,在限定的背包容量为W的情况下,如何选择物品放入背包,使得背包中物品的总价值最大。

分支限界法的基本思想是:通过不断地分解问题为更小的子问题,并使用估算函数对子问题进行优先级排序,将优先级最高的子问题优先求解。

具体步骤如下:1.根节点:将背包容量W和物品序号0作为初始状态的根节点。

2.扩展节点:对于任意一个节点S,选择装入下一个物品或者不装入两种分支。

计算新节点的上界。

3.优先级队列:将扩展节点按照上界从大到小的顺序插入优先级队列。

4.剪枝条件:当扩展节点的上界小于当前已找到的最优解时,可以剪枝。

5.结束条件:当到叶节点或者队列为空时,结束。

若叶节点的上界高于当前最优解,更新最优解。

三、实验过程1.输入数据:给定一个物品序列,每个物品有重量和价值,以及一个背包的最大容量。

2.算法实现:根据算法原理,使用编程语言实现分支限界法的求解过程。

3.结果分析:比较算法求解得到的最优解和其他算法(如动态规划)得到的最优解之间的差异。

四、实验结果以一个具体的案例来说明分支限界法的求解过程。

假设有4个物品,其重量和价值分别为{2,3,4,5}和{3,4,5,6},背包的最大容量为8、通过分支限界法求解,得到最优解为9,对应的物品选择为{2,3,5}。

通过与动态规划算法的结果比较,可以发现分支限界法的最优解与动态规划算法得到的最优解是一致的。

分支限界法实验(单源最短路径)

分支限界法实验(单源最短路径)

分⽀限界法实验(单源最短路径)算法分析与设计实验报告第七次实验基本思想:附录:完整代码(分⽀限界法)Shorest_path.cpp//单源最短路径问题分⽀限界法求解#include#include#include#include"MinHeap2.h"using namespace std;templateclass Graph //定义图类{friend int main();public:void shortest_path(int); private:int n, //图的顶点数*prev; //前驱顶点数组Type **c, //图的邻接矩阵*dist; //最短距离数组};templateclass MinHeapNode //最⼩堆中的元素类型为MinHeapNode{friend Graph;public:operator int() const{return length;}private:int i; //顶点编号Type length; //当前路长};//单源最短路径问题的优先队列式分⽀限界法templatevoid Graph::shortest_path(int v){MinHeap> H(1000);//定义最⼩堆的容量为1000//定义源为初始扩展结点MinHeapNode E;//初始化源结点E.i=v;E.length=0;dist[v]=0;while(true)//搜索问题的解空间{for(int j=1;j<=n;j++)if((c[E.i][j]!=0)&&(E.length+c[E.i][j]{//顶点i到顶点j可达,且满⾜控制约束//顶点i和j之间有边,且此路径⼩于原先从源点i到j的路径长度dist[j]=E.length+c[E.i][j];//更新dist数组prev[j]=E.i;//加⼊活结点优先队列MinHeapNode N;N.i=j;N.length=dist[j];H.Insert(N);//插⼊到最⼩堆中}try{H.DeleteMin(E); // 取下⼀扩展结点}catch (int){break;}if(H.currentsize==0)//优先队列空{break;}}}int main(){int n=11;int prev[12]={0,0,0,0,0,0,0,0,0,0,0,0};//初始化前驱顶点数组intdist[12]={1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000};//初始化最短距离数组cout<<"单源图的邻接矩阵如下:"<int **c=new int*[n+1];for(int i=1;i<=n;i++) //输⼊图的邻接矩阵{c[i]=new int[n+1];for(int j=1;j<=n;j++){cin>>c[i][j];}}int v=1; //源结点为1Graph G;G.n=n;G.c=c;G.dist=dist;G.prev=prev;clock_t start,end,over; //计算程序运⾏时间的算法start=clock();end=clock();over=end-start;start=clock();G.shortest_path(v);//调⽤图的最短路径查找算法//输出从源结点到⽬的结点的最短路径cout<<"从S到T的最短路长是:"<for(int i=2;i<=n;i++)//输出每个结点的前驱结点{cout<<"prev("<}for(int i=2;i<=n;i++) //输出从源结点到其他结点的最短路径长度{cout<<"从1到"<}for(int i=1;i<=n;i++) //删除动态分配时的内存{delete[] c[i];}delete[] c;c=0;end=clock();printf("The time is %6.3f",(double)(end-start-over)/CLK_TCK); //显⽰运⾏时间cout< system("pause");return 0;}MinHeap.h#includetemplateclass Graph;templateclass MinHeap //最⼩堆类{templatefriend class Graph;public:MinHeap(int maxheapsize=10); //构造函数,堆的⼤⼩是10~MinHeap(){delete[] heap;} //最⼩堆的析构函数int Size() const{return currentsize;} //Size()返回最⼩堆的个数T Max(){if(currentsize) return heap[1];} //第⼀个元素出堆MinHeap& Insert(const T& x); //最⼩堆的插⼊函数MinHeap& DeleteMin(T& x); //最⼩堆的删除函数void Initialize(T x[],int size,int ArraySize); //堆的初始化void Deactivate();void output(T a[],int n);private:int currentsize,maxsize;T *heap;};templatevoid MinHeap::output(T a[],int n) //输出函数,输出a[]数组的元素{for(int i=1;i<=n;i++)cout<cout<}templateMinHeap::MinHeap(int maxheapsize){maxsize=maxheapsize;heap=new T[maxsize+1]; //创建堆currentsize=0;}templateMinHeap& MinHeap::Insert(const T& x){if(currentsize==maxsize) //如果堆中的元素已经等于堆的最⼤⼤⼩return *this; //那么不能在加⼊元素进⼊堆中int i= ++currentsize;while(i!=1 && x{heap[i]=heap[i/2];i/=2;}heap[i]=x;return *this;}templateMinHeap& MinHeap::DeleteMin(T& x) //删除堆顶元素{if(currentsize==0){cout<<"Empty heap!"<return *this;}x=heap[1];T y=heap[currentsize--];int i=1,ci=2;while(ci<=currentsize){if(ciheap[ci+1])ci++;if(y<=heap[ci])break;heap[i]=heap[ci];i=ci;ci*=2;}heap[i]=y;return *this;}templatevoid MinHeap::Initialize(T x[],int size,int ArraySize) //堆的初始化{ delete[] heap;heap=x;currentsize=size;maxsize=ArraySize;for(int i=currentsize/2;i>=1;i--){T y=heap[i];int c=2*i;while(c<=currentsize){if(cheap[c+1])c++;if(y<=heap[c])break;heap[c/2]=heap[c];c*=2;}heap[c/2]=y;}}templatevoid MinHeap::Deactivate() {heap=0;}。

实验5分支限界(精)

实验5分支限界(精)

《算法设计与分析》实验报告实验5 分支限界算法姓名学号班级网络131实验日期2016.11.29 实验地点学院305一、实验目的:掌握分支限界算法的设计思想与设计方法。

二、实验环境1、硬件环境CPU:2.0GHz内存:4GB硬盘:100GB2、软件环境操作系统:win7编程环境:devc++编程语言:c三、实验内容1、问题有一个背包,最大限重为C,有n个物品,重量分别为W=<w1, w2, …, wn>,价值分别为V=<v1, v2, …, vn>要求使用分支限界算法找出一个装载方案,使得放入背包物品的价值之和最大。

输出装载方案和该方案下的背包所装物品总重量及总价值。

2、数据结构(1)解的结构typedef struct treenode(2)搜索空间的结构int bbfifoknap(int w[],int v[],int n,int c,int* bestValue)3、算法伪代码PackSolu(G, n, C)输入: G[]存储物品的数据结构,n表示物品个数,C表示背包容量输出:一个用来存储各个物品装入数目的数组1. Sort(G) // 将物品从大到小排序2. v<-0; w<-0; i<-0; // v表示装入背包的总值,w表示装入背包的总重,i表示物品的索引3. while i < n do4. if 背包可装下j个第i种物品5. then v<-(v+G[i].v);w<-(w+G[i].w);solu[i] = 1;6. else solu[i] = 0;7. if v >界的值best_v then 更新最优解8. while solu[i] = 0 and i > 0 do i--; // 回溯到上一个装入的物品9. if solu[i] > 0 then solu[i] = 0;w<-(w-G[i].w);v<-(v-G[i].v);i++10. if i > 0 then goto 34、算法分析时间复杂度:O(2^n)空间复杂度:O(n)5、关键代码(含注释)#include<iostream>#include<queue>using namespace std;typedef struct treenode{int weight;int value;int level;int flag;}treenode;queue<struct treenode> que;int enQueue(int w,int v,int level,int flag,int n,int* bestvalue) {treenode node;node.weight = w;node.value = v;node.level = level;node.flag = flag;if (level == n){if (node.value > *bestvalue){*bestvalue = node.value;}return 0;}else{que.push(node);}}//w为重量数组,v为价值数组,n为物品个数,c为背包容量,bestValue为全局最大价值int bbfifoknap(int w[],int v[],int n,int c,int* bestValue){//初始化结点int i=1;treenode tag, livenode;livenode.weight = 0;livenode.value = 0;livenode.level = 1;livenode.flag = 0;//初始为0tag.weight = -1;tag.value = 0;tag.level = 0;tag.flag = 0;//初始为0que.push(tag);while (1){if (livenode.weight + w[i - 1] <= c){enQueue(livenode.weight + w[i - 1], livenode.value + v[i - 1], i, 1,n,bestValue);}enQueue(livenode.weight,livenode.value, i, 0,n,bestValue);livenode = que.front();que.pop();if (livenode.weight == -1){if (que.empty() == 1){break;}livenode = que.front();que.pop();que.push(tag);i++;}}return 0;}6、实验结果(1)输入:C=10,n=4,W=<7, 4, 3, 2>,V=<9, 5, 3, 1>输出:12(2)输入:C=10,n=5,V=<10, 32, 12, 20, 18>,W=<1, 4, 2, 4, 6>输出:64四、实验总结(心得体会、需要注意的问题等)这次学习的是分支界限算法。

分支限界算法报告

分支限界算法报告

实验五分支限界算法的应用一、实验目的1 •掌握分支限界算法的基本思想、技巧和效率分析方法。

2•熟练掌握用分支限界算法的基本步骤和算法框架,FIFO搜索,LIFO搜索,优先队列式搜索的思想。

3 •学会利用分支限界算法解决实际问题。

二、算法问题描述批处理作业调度问题:n个作业{1,2,…,要在两台机器上处理,每个作业必须先由机器1处理,然后再由机器2处理,机器1处理作业i所需时间为ai,机器2处理作业i 所需时间为bi ( K i菊n,批处理作业调度问题(batch-job scheduling problem)要求确定这n个作业的最优处理顺序,使得从第1个作业在机器1上处理开始,到最后一个作业在机器2上处理结束所需时间最少。

注意:由于要从n个作业的所有排列中找出具有最早完成时间的作业调度,所以,批处理作业调度问题的解空间是一棵排列树,并且要搜索整个解空间树才能确定最优解,因此,其时间性能是O(n!)。

在搜索过程中利用已得到的最短完成时间进行剪枝,才能够提高搜索速度。

三、算法设计批处理作业调度问题要从n个作业的所有排列中找出具有最小完成时间和的作业调度,所以如图,批处理作业调度问题的解空间是一颗排列树业集:1--'……:。

以该节点为根的子树中所含叶节点的完成时间和可表示为:匸工代+工的设|M|=r ,且L 是以节点E 为根的子树中的叶节点,相应的作业调度为{pk,k=1,2,……n},其中pk 是第k 个安排的作业。

如果从节点 E 到叶节点L 的 路上,每一个作业pk 在机器1上完成处理后都能立即在机器 2上开始处理,即 从p 叶1开始,机器1没有空闲时间,则对于该叶节点 L 有:IX 二£ [%+心+1)仏+切」諾踰 也'+! 注:(n-k+1)t1pk,因为是完成时间和,所以,后续的(n-k+1)个作业完成时间和都得算上tlpk 。

如果不能做到上面这一点,则si 只会增加,从而有: 。

分支限界法实验(单源最短路径)

分支限界法实验(单源最短路径)

算法分析与设计实验报告第七次实验姓名学号班级时间12.26上午地点工训楼309实验名称分支限界法实验(单源最短路径)实验目的1.掌握并运用分支限界法的基本思想2.运用分支限界法实现单源最短路径问题实验原理问题描述:在下图所给的有向图G中,每一边都有一个非负边权。

要求图G的从源顶点s 到目标顶点t之间的最短路径。

基本思想:下图是用优先队列式分支限界法解有向图G的单源最短路径问题产生的解空间树。

其中,每一个结点旁边的数字表示该结点所对应的当前路长。

为了加速搜索的进程,应采用有效地方式选择活结点进行扩展。

按照优先队列中规定的优先级选取优先级最高的结点成为当前扩展结点。

catch (int){break;}if(H.currentsize==0) //优先队列空{break;}}}上述有向图的结果:测试结果附录:完整代码(分支限界法)Shorest_path.cpp//单源最短路径问题分支限界法求解#include<iostream>#include<time.h>#include<iomanip>#include"MinHeap2.h"using namespace std;template<class Type>class Graph //定义图类{friend int main();public:void shortest_path(int); private:int n, //图的顶点数*prev; //前驱顶点数组Type **c, //图的邻接矩阵*dist; //最短距离数组};template<class Type>class MinHeapNode //最小堆中的元素类型为MinHeapNode{friend Graph<Type>;public:operator int() const{return length;}private:int i; //顶点编号Type length; //当前路长};//单源最短路径问题的优先队列式分支限界法template<class Type>void Graph<Type>::shortest_path(int v){MinHeap<MinHeapNode<Type>> H(1000);//定义最小堆的容量为1000//定义源为初始扩展结点MinHeapNode<Type> E;//初始化源结点E.i=v;E.length=0;dist[v]=0;while(true)//搜索问题的解空间{for(int j=1;j<=n;j++)if((c[E.i][j]!=0)&&(E.length+c[E.i][j]<dist[j])){//顶点i到顶点j可达,且满足控制约束//顶点i和j之间有边,且此路径小于原先从源点i到j的路径长度dist[j]=E.length+c[E.i][j];//更新dist数组prev[j]=E.i;//加入活结点优先队列MinHeapNode<Type> N;N.i=j;N.length=dist[j];H.Insert(N);//插入到最小堆中}try{H.DeleteMin(E); // 取下一扩展结点}catch (int){break;}if(H.currentsize==0)//优先队列空{break;}}}int main(){int n=11;int prev[12]={0,0,0,0,0,0,0,0,0,0,0,0};//初始化前驱顶点数组intdist[12]={1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000 };//初始化最短距离数组cout<<"单源图的邻接矩阵如下:"<<endl;int **c=new int*[n+1];for(int i=1;i<=n;i++) //输入图的邻接矩阵{c[i]=new int[n+1];for(int j=1;j<=n;j++){cin>>c[i][j];}}int v=1; //源结点为1Graph<int> G;G.n=n;G.c=c;G.dist=dist;G.prev=prev;clock_t start,end,over; //计算程序运行时间的算法start=clock();end=clock();over=end-start;start=clock();G.shortest_path(v);//调用图的最短路径查找算法//输出从源结点到目的结点的最短路径cout<<"从S到T的最短路长是:"<<dist[11]<<endl;for(int i=2;i<=n;i++)//输出每个结点的前驱结点{cout<<"prev("<<i<<")="<<prev[i]<<" "<<endl;}for(int i=2;i<=n;i++) //输出从源结点到其他结点的最短路径长度{cout<<"从1到"<<i<<"的最短路长是:"<<dist[i]<<endl;}for(int i=1;i<=n;i++) //删除动态分配时的内存{delete[] c[i];}delete[] c;c=0;end=clock();printf("The time is %6.3f",(double)(end-start-over)/CLK_TCK); //显示运行时间cout<<endl;system("pause");return 0;}MinHeap.h#include<iostream>template<class Type>class Graph;template<class T>class MinHeap //最小堆类{template<class Type>friend class Graph;public:MinHeap(int maxheapsize=10); //构造函数,堆的大小是10~MinHeap(){delete[] heap;} //最小堆的析构函数int Size() const{return currentsize;} //Size()返回最小堆的个数T Max(){if(currentsize) return heap[1];} //第一个元素出堆MinHeap<T>& Insert(const T& x); //最小堆的插入函数MinHeap<T>& DeleteMin(T& x); //最小堆的删除函数void Initialize(T x[],int size,int ArraySize); //堆的初始化void Deactivate();void output(T a[],int n);private:int currentsize,maxsize;T *heap;};template<class T>void MinHeap<T>::output(T a[],int n) //输出函数,输出a[]数组的元素{for(int i=1;i<=n;i++)cout<<a[i]<<" ";cout<<endl;}template<class T>MinHeap<T>::MinHeap(int maxheapsize){maxsize=maxheapsize;heap=new T[maxsize+1]; //创建堆currentsize=0;}template<class T>MinHeap<T>& MinHeap<T>::Insert(const T& x){if(currentsize==maxsize) //如果堆中的元素已经等于堆的最大大小return *this; //那么不能在加入元素进入堆中int i= ++currentsize;while(i!=1 && x<heap[i/2]){heap[i]=heap[i/2];i/=2;}heap[i]=x;return *this;}template<class T>MinHeap<T>& MinHeap<T>::DeleteMin(T& x) //删除堆顶元素{if(currentsize==0){cout<<"Empty heap!"<<endl;return *this;}x=heap[1];T y=heap[currentsize--];int i=1,ci=2;while(ci<=currentsize){if(ci<currentsize && heap[ci]>heap[ci+1])ci++;if(y<=heap[ci])break;heap[i]=heap[ci];i=ci;ci*=2;}heap[i]=y;return *this;}template<class T>void MinHeap<T>::Initialize(T x[],int size,int ArraySize) //堆的初始化{delete[] heap;heap=x;currentsize=size;maxsize=ArraySize;for(int i=currentsize/2;i>=1;i--){T y=heap[i];int c=2*i;while(c<=currentsize){if(c<currentsize && heap[c]>heap[c+1])c++;if(y<=heap[c])break;heap[c/2]=heap[c];c*=2;}heap[c/2]=y;}}template<class T>void MinHeap<T>::Deactivate(){heap=0; }。

分枝限界法_实验报告

分枝限界法_实验报告

一、课题名称用分枝限界法求解单源最短路径问题二、课题内容和要求设计要求:学习算法设计中分枝限界法的思想,设计算法解决数据结构中求解单源最短路径问题,编程实现:(1)给出指定源点的单源最短路径;(2)说明算法的时间复杂度。

三、需求分析1.实现极小堆的创建,用来存储活结点表。

2.实现循环队列的创建、初始化、入队、出队等操作。

3.实现分支限界法来实现求解单元最短路径的算法。

4.实现最短路径的正确输出。

四、概要设计建立工程MinPath.dsw,加入源文件main.cpp,头文件CirQueue.h,init.h,Minpath.h和output.h. CirQueue.h中实现极小堆的创建,循环队列的创建、初始化、入队、出队等操作,Minpath.h中实现分支限界法来实现求解单元最短路径的算法。

output.h中实现最短路径的正确输出。

如下图所示:实验用例如下,通过邻接矩阵的方式写在init.h 中:五、详细设计12581134 69 7103 43292212223733352main函数:#include<iostream.h>#include"init.h"#include"CirQueue.h"#include"MinPath.h"#include"output.h"void main(){int k;int q;cout<<"------------欢迎使用本系统---------------"<<endl;cout<<"------------请选择单元路径的起点:---------------"<<endl;cout<<"------------提示:输入"<<1<<"到"<<n-1<<"之间的整数---------------"<<endl;cin>>k;cout<<"------------请选择单元路径的终点:---------------"<<endl;cin>>q;while(k<1||k>11){cout<<"------------提示:输入"<<1<<"到"<<n-1<<"之间的数,请重新输入---------------"<<endl;cin>>k;}MinPath(k);output(k,q);}init.hconst int size = 200;const int inf = 1000; //两点距离上界置为1000const int n = 12; //图顶点个数加1int prev[n]; //图的前驱顶点int dist[] = {0,inf,inf,inf,inf,inf,inf,inf,inf,inf,inf,inf}; //最短距离数组int c[n][n] = {{0,0,0,0,0,0,0,0,0,0,0,0},{0,0,2,3,4,inf,inf,inf,inf,inf,inf,inf},{0,inf,0,3,inf,7,2,inf,inf,inf,inf,inf},{0,inf,inf,0,inf,inf,9,2,inf,inf,inf,inf},{0,inf,inf,inf,0,inf,inf,2,inf,inf,inf,inf},{0,inf,inf,inf,inf,0,inf,inf,3,3,inf,inf},{0,inf,inf,inf,inf,inf,0,1,inf,3,inf,inf},{0,inf,inf,inf,inf,inf,inf,0,inf,5,1,inf},{0,inf,inf,inf,inf,inf,inf,inf,0,inf,inf,3},{0,inf,inf,inf,inf,inf,inf,inf,inf,0,inf,2},{0,inf,inf,inf,inf,inf,inf,inf,inf,2,inf,2},{0,inf,inf,inf,inf,inf,inf,inf,inf,inf,inf,0},}; //图的邻接矩阵CirQueue.hclass MinHeapNode//创建极小堆用来存储活结点表{public :int i; //顶点编号int length; //当前路长};class CirQueue//循环队列{private:int front,rear;//头指针和尾指针MinHeapNode data[size];public:CirQueue()//初始化建空队列{front = rear = 0;}void queryIn(MinHeapNode e)//元素入队操作{if((rear +1)%size != front)//队列未满{rear = (rear+1)%size; //插入新的队尾元素data[rear] = e; //在队尾插入元素 }}void queryOut()//元素出队操作{if(rear != front){front = (front+1)%size; //删除队头元素}}MinHeapNode getQuery()//读取队头元素,但不出队 {if(rear != front){return data[(front+1)%size];}return data[1];}bool empty()//判断队列是否为空{return front == rear;}bool full()//判断队列是否为满{return (rear +1)%size == front;}};//CirQueue结束MainPath.hvoid MinPath(int v){CirQueue s;//定义源为初始扩展结点MinHeapNode e;e.i = v;e.length = 0;dist[v] = 0;s.queryIn(e); //将源节点加入队列while(true){for(int j = 1;j<n;j++){if(j>=n){break;}MinHeapNode m = s.getQuery();if((c[m.i][j]<inf)&&(m.length + c[m.i][j] < dist[j]))//顶点i到顶点j可达,且从源出发途经i到j的路径长度小于当前最优路径长度{dist[j] = m.length + c[m.i][j];prev[j] = m.i;MinHeapNode mi;//加入活结点优先队列mi.i = j;mi.length = dist[j];if(s.full()){break;}s.queryIn(mi); //元素入队}}//for循环结束if(s.empty()){break;}s.queryOut(); //当该结点的孩子结点全部入队后,删除该结点 }//while循环结束}//方法结束output.hvoid output(int k,int q){int q1=q;if(dist[q1]==1000){cout<<"------------找不到此路径---------------"<<endl;return;}cout<<"最短路径长为: "<<dist[q1]<<endl;cout<<"单源最短路径为: ";int a[12]={0};int t =q1;int s=0;for(int i=0;t!=k;i++){a[i] = prev[t];t = prev[t];s=s+1;}for(i=s-1;i>-1;i--) {cout<<a[i]<<" ";}cout<<q1;cout<<endl<<"------------欢迎使用本系统---------------"<<endl; }六、测试数据及其结果分析1.选择起点:1,终点:111到11最短路径长为8,为1->3->7->10->11所获得。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

注 : (n-k+1)t1pk, 因 为是完成时间和,所以,后续的(n-k+1)个作业完成时间和都得算上 t1pk。
如果不能做到上面这一点,则 s1 只会增加,从而有:

类似地,如果从节点 E 开始到节点 L 的路上,从作业 pr+1 开始,机器 2 没
有空闲时间,则:
精品文档交流
2
同理可知,s2 是 节点完成时间和的下界是:
【下载本文档,可以自由复制内容或自由编辑修改内容,更
多精彩文章,期待你的好评和关注,我将一如既往为您服务】
精品文档交流
5
实验五 分支限界算法的应用
一、实验目的
1.掌握分支限界算法的基本思想、技巧和效率分析方法。 2.熟练掌握用分支限界算法的基本步骤和算法框架,FIFO 搜索,LIFO 搜
索,优先队列式搜索的思想。 3.学会利用分支限界算法解决实际问题。
二、算法问题描述
批处理作业调度问题:n 个作业{1, 2, …, n}要在两台机器上处理,每个作业 必须先由机器 1 处理,然后再由机器 2 处理,机器 1 处理作业 i 所需时间为 ai, 机器 2 处理作业 i 所需时间为 bi(1≤i≤n),批处理作业调度问题(batch-job scheduling problem)要求确定这 n 个作业的最优处理顺序,使得从第 1 个作业在 机器 1 上处理开始,到最后一个作业在机器 2 上处理结束所需时间最少。
在作业调度问相应的排列空间树中,每一个节点 E 都对应于一个已安排的作
业集 表示为:
。以该节点为根的子树中所含叶节点的完成时间和可
设|M|=r,且 L 是以节点 E 为根的子树中的叶节点,相应的作业调度为 {pk,k=1,2,……n},其中 pk 是第 k 个安排的作业。如果从节点 E 到叶节点 L 的 路上,每一个作业 pk 在机器 1 上完成处理后都能立即在机器 2 上开始处理,即 从 pr+1 开始,机器 1 没有空闲时间,则对于该叶节点 L 有:
Backtrace(t+1); } swap(x[t],x[i]); f1-=m[1][x[i]]; f-=f2[t]; } } } int main() { memset(bestx,0,(N+1)*sizeof(int)); memset(f2,0,(N+1)*sizeof(int));
精品文档交流
的下界。由此得到在节点 E 处相应子树中叶
注意到如果选择 Pk,使 t1pk 在 k>=r+1 时依非减序排列,S1 则取 得极小值。同理如果选择 Pk 使 t2pk 依非减序排列,则 S2 取得极小值。
这可以作为优先队列式分支限界法中的限界函数。
四、运行结果
五、程序
#include<stdio.h> #include<string.h> #define N 4//作业数目设定为 4 #define MAX 1000 int x[N+1]={0,1,2,3}; int m[4][N+1]={
int temp=a; a=b; b=temp; } void Backtrace(int t) { if(t>N) {
bestf=f; for(int i=1;i<=N;i++) {
bestx[i]=x[i]; } } else {
for(int i=t;i<=N;i++) { f1+=m[1][x[i]]; f2[t]=(f2[t-1]>f1?f2[t-1]:f1)+m[2][x[i]]; f+=f2[t]; swap(x[t],x[i]); if(f<bestf) {
0,0,0,0, 0,2,3,2, 0,1,1,3, 0,2,2,1
机; int bestx[N+1];//用于保存结果调度顺序 int f2[N+1];//第 i 阶段机器 2 完成处理的时间 int f1=0;//机器 1 完成处理时间 int f=0;//当前完成时间和 int bestf=MAX; void swap(int &a,int &b) {
4
Backtrace(1); printf("该作业调度的最优完成时间和为:%d\n 调度顺序为:\n\n",bestf); for(int i=1;i<=N;i++) {
printf("%d\n",bestx[i]); } return 0; }
六、总结
每个人对分支限定法的算法都存在着一定的理解,这也就是很多同学的算法实现 不同的原因.可能是自己理解的不够透彻,我总觉得自己的实验做的非常的不完 善。发现自己还存在着很大差距.希望通过更多的实验,让自己有更大的提高.
注意:由于要从 n 个作业的所有排列中找出具有最早完成时间的作业调度, 所以,批处理作业调度问题的解空间是一棵排列树,并且要搜索整个解空间树才 能确定最优解,因此,其时间性能是 O(n!)。在搜索过程中利用已得到的最短完 成时间进行剪枝,才能够提高搜索速度。
三、算法设计
批处理作业调度问题要从 n 个作业的所有排列中找出具有最小完成时间和 的作业调度,所以如图,批处理作业调度问题的解空间是一颗排列树。
相关文档
最新文档