算法分析与设计 实验报告 分支限界法:最优及其优化
算法设计与分析---分支界限法实验报告

《算法设计与分析》实验报告实验四分治限界法1. 迷宫最短路径在下图中,请使用广度搜索求出a到b的最短路径,有色区域为不可通过区域。
2. 树上最短路径dashen是个牛人。
很多人都想认识dashen,但没有这个机会,于是shen粉们便想了一个方法,计算自己与dashen的ACM距离,因此很多人都去参加ACM,而ACM因此也改名为ACM国际水赛。
每个ACM有n个组,每组3个人。
同组的3个人都是队友。
大家都想知道自己与dashen的最小距离是多少。
dashen与自己的最小距离当然是0。
dashen的队友和dashen的最小距离是1。
dashen的队友的队友和dashen的最小距离是2……以此类推。
如果实在和dashen没有关系的只好输出undefined了。
1. 迷宫最短路径1.2 解题思路迷宫搜索最短路径,主要考察的就是最简单裸的BFS。
BFS只要掌握如何标记好数组、边界的考虑、出队进队就好了。
如何保存搜索的层数?每一次节点扩散层,标记的层数值都是当前层的+1 即可。
至于写BFS的写法。
步骤都是一样的:放第一个进队,然后出队、扩散开进队并标记、出队......循环下去直到队空。
写法太基础就不讲解了。
1.2 测试样例73 24 6..#......##.......#.....##..#...#..###....###....1.3 程序运行情况2.3 程序运行情况2.4 程序源码(含注释)#include"bits/stdc++.h"using namespace std;#define inf 999#define INF 999999999int n,num;//行数,以及不重复人数int origin;// 起点,即dashen 的标号int book[inf];//标记vector<int>edge[inf];//每个点的边集struct Student{//学生类,下标自1始string name;int id;int rank;void set(string s,int i){name=s;id=i;rank=INF;//所有人的距离默认无穷大。
实验五:分枝限界法-最短路径问题

HUBEI UNIVERSITY OF AUTOMOTIVE TECHNOLOGY算法设计与分析实验报告实验项目实验五实验类别验证性学生姓名王龙学生学号201400797 完成日期2016-5-6指导教师刘振章实验成绩评阅日期评阅教师刘振章实验五:分枝限界法【实验目的】应用分枝限界法的算法设计思想求解单源最短路径问题。
【实验性质】验证性实验。
【实验内容与要求】采用分支限界法编程求源点0到终点6的最短路径及其路径长度。
要求完成:⑴算法描述⑵写出程序代码⑶完成调试⑷进行过程与结果分析。
【算法思想及处理过程】由于要找的是从源到各顶点的最短路径,所以选用一个数组存起来.Fenzhi函数: 由于先前赋值时, 用一个二维数组将结点的有向图标记存起来了( 有边为1, 无边为0 ),并且又用另外一个二维数组将其权重存起来了; 首先, 通过双重for循环, 通过if语句判断, 如果标记为1, 并且相加的权重小于先前最优权重( 在初始化的时候, 对最优权重赋上一个最大值 ), 则求得最优权重, 并且用一维数组将权重存起来, 而且用一维数组将前驱结点存起来.你然后, 一直循环下去, 直到循环到目的结点.【程序代码】for (z=0; z<k; z++){scanf ("%d %d %d", &i, &j, &m);t[i][j] = m;ti[i][j] = 1;}for (i = 0; i < n; i++) //初始化数组{d[i] = 99; // 赋个最大值s[i] = -1;}}void fenzhi (int d[], int s[],int t[][MAX], int ti[][MAX], int n, int k) {int i, j, zi;d[0]=0; s[0]=-1;for (i=0; i<n; i++){printf ("当前扩展节点:%d,权重:%d : \n", i, d[i]);for (j=0; j<n; j++){if (ti[i][j] == 1 ){if ( d[j]>t[i][j]+d[i]){d[j]=t[i][j]+d[i]; //最短长度s[j]=i; //前驱结点}if (j != n /* && j != 6 */ )printf ("入队结点:%d ,最优权重:%d \n", j, d[j]);}}printf ("\n");}}void output (int d[], int s[], int n){int i, j=0, zi[MAX];printf ("从源点到各个结点的最短路径: \n");for (i=0; i<n; i++)printf ("dist[%d] = %d \n", i, d[i]);printf ("\n");printf ("从源点到终点的最短路径长度为: %d \n", d[n-1]);printf ("其路径为: %d ", n-1);zi[j] = s[n-1];printf ("----> %d ", zi[j]);while (zi[j] != 0){j++;zi[j] = s[zi[j-1]];printf ("----> %d ", zi[j]);}printf ("\n");}【运行结果】图1 输入数据图2 输出扩展结点图3 最终结果【算法分析】本程序的主要函数ShorestPaths的时间复杂度为: O ( n * (n-1) ), 最坏时间复杂度为: O ( n*n )【实验总结】。
算法分析与设计分支限界法

算法分析与设计分支限界法分支限界法是一种常用的优化算法,它通过剪枝和分支的方式在空间中找到最优解。
在算法设计与分析中,分支限界法在求解组合优化问题和图论问题中有广泛应用。
分支限界法的基本思想是将问题划分为一个个子问题,并对每个子问题进行求解,同时通过剪枝操作减少空间。
算法从一个初始状态开始,通过扩展子节点来生成树。
在每个节点上,先判断该节点是否需要剪枝操作。
如果需要剪枝,则舍弃该节点及其子节点;如果不需要剪枝,则继续扩展该节点为新的可能解。
通过不断扩展和剪枝操作,最终找到最优解。
分支限界法的核心是选择一个合适的策略来确定节点的扩展顺序。
常用的策略包括优先级队列、最小堆、最大堆等。
这些策略可以根据问题的性质和特点来选择,以保证效率。
同时,剪枝操作也是分支限界法中关键的一环。
剪枝操作有多种方式,如上界和下界剪枝、可行剪枝、标杆剪枝等。
通过剪枝操作,可以减少空间,提高算法的效率。
分支限界法的时间复杂度通常是指数级别的,因为每个节点需要根据策略进行扩展,并进行剪枝操作。
然而,通过合理选择策略和剪枝操作,可以显著减少空间,降低时间复杂度。
此外,分支限界法还可以通过并行计算等技术进一步提高效率。
分支限界法在求解组合优化问题中有广泛应用。
组合优化问题是在有限的资源条件下,通过组合和选择来达到最优解的问题。
例如,旅行商问题、背包问题等都是经典的组合优化问题,而分支限界法可以在有限的时间内找到最优解。
在图论问题中,分支限界法也有重要的应用。
例如,最短路径问题、图着色问题等都可以通过分支限界法求解。
总之,分支限界法是一种基于和剪枝的优化算法,通过合理选择策略和剪枝操作,在有限的时间内找到最优解。
该算法在组合优化问题和图论问题中有广泛应用,可以有效提高问题求解的效率。
在实际应用中,可以根据问题性质和特点选择合适的策略和剪枝操作,以达到最佳的求解效果。
算法分析与设计实验五分枝—限界算法

算法分析与设计实验五分枝—限界算法1、实现0/1背包问题的LC分枝—限界算法,要求使用大小固定的元组表示动态状态空间树,与0/1背包问题回溯算法做复杂性比较。
2、实现货郎担问题的分枝—限界算法并与货郎担问题的动态规划算法做复杂性比较比较。
3、实现带有期限的作业排序的分枝—限界算法并与带有期限的作业排序贪心算法做复杂性比较。
(任选一个完成)实验六分枝—限界算法实验目的1.掌握分枝—限界的基本思想方法;2.了解适用于用分枝—限界方法求解的问题类型,并能设计相应动态规划算法;3.掌握分枝—限界算法复杂性分析方法,分析问题复杂性。
预习与实验要求1.预习实验指导书及教材的有关内容,掌握分枝—限界的基本思想;2.严格按照实验内容进行实验,培养良好的算法设计和编程的习惯;3.认真听讲,服从安排,独立思考并完成实验。
实验设备与器材硬件:PC机软件:C++或Java等编程环境实验原理分枝—限界算法类似于回溯法,也是一种在问题的解空间树上搜索问题解的算法。
但两者求解方法有两点不同:第一,回溯法只通过约束条件剪去非可行解,而分枝—限界法不仅通过约束条件,而且通过目标函数的限界来减少无效搜索,也就是剪掉了某些不包含最优解的可行解;第二,在解空间树上,回溯法以深度优先搜索,而分枝—限界法则以广度优先或最小耗费优先的方式搜索。
分枝—限界的搜索策略是,在扩展节点处,首先生成其所有的儿子结点(分支),然后再从当前的活结点表中选择下一个扩展结点。
为了有效地选择下一扩展结点,以加速搜索进程,在每一活结点处,计算一个函数值(限界),并根据这些已计算出的函数值从当前活结点表中选择一个最有利的结点做为扩展,使搜索朝着解空间树上最优解的分支推进,以便尽快找出一个最优解。
分枝—限界法常以广度优先或以最小耗费优先的方式搜索问题的解空间树(问题的解空间树是表示问题皆空间的一颗有序树,常见的有子集树和排序树)。
在搜索问题的解空间树时,分枝—限界法的每一个活结点只有一次机会成为扩展结点。
算法设计与分析 分支限界

…
13
纲要
一、分支限界的基本思想
二、背包问题
三、P和NP
14
问题定义
0-1背包问题
给定n个物品,商品i有两个属性i 和i ,分别代表重量和价格,
背包所承受的物品重量为W
0-1背包问题的目的是要选择一个物品的子集,使其总重量≤W,而价值最大。
解空间
假设解可以有向量( , ,…, )表示, ∈{0,1}, =1表示物品i被放进
(成为死节点),把剩下来的节点加到活节点的表中,然后,从这个
表中选一个节点作为下一个扩展节点。
7
分支限界法
从活节点的表中选一个节点并扩展它。这个扩展操作持续到找到解或这
个表为空为止。
选择下一个扩展节点的方法∶
1)先进先出(FIFO)
这个方法是按节点放进表中的次序从活节点表中选择节点。这个活节点
表可被看作一个队列。使用广度优先来搜索这个棵树。
在这个节点上我们得到的下界大于或等于上界,那么就没有必要在扩
展这个节点既不需在延伸这个分支。
·对于最大化问题规则正好相反:一旦上界小于或等于先前确定的下界,
那么就剪掉这个枝。
4
分支限界法
·首先,分支限界是对最优化问题可行解进行剪枝的一个方法。
·将搜索集中在有希望得到解的分支上。也就是说,在基于上下界和可
时,活节点表可用一个最大堆来表示。下一个扩展节点为最大收益的节点。
9
解空间树
扩展节点
死节点
活节点
success
10
分支限界法
使用分支限界法至少需要注意以下几点:
1.怎么样计算上界,极大值问题;
分支限界法实验(单源最短路径)

算法分析与设计实验报告第七次实验姓名学号班级时间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所获得。
单源最短路径(分支限界法)

算法分析与设计实验报告第7次实验给定下示有向图,利用分支限界法的思想,计算并输出其单源最短路径。
1 算法从图 G 的源顶点 s 和空优先队列开始。
结点 s 被扩展后,它的儿子}随机数产生图的权值:通过这次实验,我回顾了分支界限法求解最短路径问题,在其中加入了舍附录:完整代码#include <iostream>#include <queue>#include<stdlib.h>using namespace std;#define MAX 9999//定义为无限大#define N 60int n,dist[N],a[N][N];class HeapNode//最小堆来存储活节点表{public:int i,length;//顶点编号,当前的路径长度HeapNode() { }HeapNode(int ii,int l){i=ii;length=l;}bool operator<(const HeapNode& node)const{return length<node.length;}};void shorest(int v){priority_queue<HeapNode> heap;HeapNode enode(v,0);for(int i=1; i<=n; i++) dist[i]=MAX;dist[v]=0;//搜索问题的解空间while(1){for(int j=1; j<=n; j++)if(a[enode.i][j]<MAX && enode.length+a[enode.i][j]<dist[j])//顶点I 到J是可达的,并且满足控制约束{dist[j]=enode.length+a[enode.i][j];HeapNode node(j,dist[j]);heap.push(node);//加入活节点优先队列}if(heap.empty()) break;//优先队列为空else{enode=heap.top();heap.pop();}}}int main (){int v,i;cout<<"个数:";cin>>n;cout<<"源点:";cin>>v;for(int i=1; i<=n; i++)for(int j=1; j<=n; j++){if(i!=j){if((a[j][i]==0)||(a[j][i]==MAX))a[i][j]=rand()%100+1;else a[i][j]=MAX;if(a[i][j]>50) a[i][j]=MAX;}}cout<<"\n路径: "<<endl;for( i=1;i<n+1;i++){for(int j=1;j<n+1;j++)cout<<a[i][j]<<" ";cout<<endl;}shorest(v);cout<<endl;for( i=2; i<n; i++) {cout<<v<<"到"<<i<<"的最短路径为:"<<dist[i]<<endl; }cout<<v<<"到"<<i<<"的最短路径为:"<<dist[n]<<endl; system("pause");return 0;}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
return 0;
}
return 1;
}
void print() //打印输出N皇后的一组解
{
int i, j;
for (i = 0; i < QUEEN; ++i)
{
实验报告成绩(百分制)__________实验指导教师签字:__________
{
int *p;
for (p = a; p < a + QUEEN; ++p)
{
*p = INITIAL;
}
}
int valid(int row, int col) //判断第row行第col列是否可以放置皇后
{
int i;
for (i = 0; i < QUEEN; ++i) //对棋盘进行扫描
{
continue;
}
}
if (i == QUEEN - 1) //最后一行找到了一个皇后位置,说明找到一个结果,打印出来
{
printf("answer %d : \n", ++n);
print();
//不能在此处结束程序,因为我们要找的是N皇后问题的所有解,此时应该清除该行的皇后,从当前放置皇后列数的下一列继续探测。
武夷学院实验报告
课程名称:算法分析与设计项目名称:分支限界法:最优及其优化
姓名:专业:计算机科学班级:1班学号:同组成员:无
一、实验预习部分:
实验目的及要求
进入实验机房,加深学生理解-回溯法在智能搜索计算技术中运用实际问题求解及其通用计算机系统运行环境平台,以及智能回溯法即试探性问题求解算法与核心系统软件、计算机语言和人的智能行为间相互嵌入与支持关系的认识,如视窗操作系统Windows XP/2003/2007等平台、计算机语言选择、静态数据初始化、动态数据决策应用、人类解决问题思路嵌入信息处理过程等;使学生掌握通用经典信息处理计算技术灵活运用于问题求解个案、嵌入智能并能较好地解决问实际题。
//_sleep(600);
j = a[i] + 1; //从最后一行放置皇后列数的下一列继续探测
a[i] = INITIAL; //清除最后一行的皇后位置
continue;
}
++i; //继续探测下一行的皇后位置
}
}
int main(void)
{
init();
queen();
system("pause");
{
if(valid(i, j)) //该位置可以放置皇后
{
a[i] = j; //第i行放置皇后
j = 0; //第i行放置皇后以后,需要继续探测下一行的皇后位置,所以此处将j清零,从下一行的第0列开始逐列探测
break;续探测下一列
}
}
if(a[i] == INITIAL) //第i行没有找到可以放置皇后的位置
printf("%d ", a[i]);
printf("\n");
printf("--------------------------------\n");
}
void queen() //N皇后程序
{
int n = 0;
int i = 0, j = 0;
while (i < QUEEN)
{
while (j < QUEEN) //对i行的每一列进行探测,看是否可以放置皇后
for (j = 0; j < QUEEN; ++j)
{
if (a[i] != j) //a[i]为初始值
printf("%c ", '.');
else //a[i]表示在第i行的第a[i]列可以放置皇后
printf("%c ", '#');
}
printf("\n");
}
for (i = 0; i < QUEEN; ++i)
return 0;
}
二、实验结果与讨论:
通过回朔法解决八皇后问题,在现实中,有很多问题往往需要我们把其所有可能穷举出来,然
后从中找出满足某种要求的可能或最优的情况,从而得到整个问题的解。回溯算法就是解决这种问题的“通用算法”,有“万能算法”之称。N皇后问题在N增大时就是这样一个解空间很大的问题,所以比较适合用这种方法求解。
{
if (i == 0) //回溯到第一行,仍然无法找到可以放置皇后的位置,则说明已经找到所有的解,程序终止
break;
else //没有找到可以放置皇后的列,此时就应该回溯
{
--i;
j = a[i] + 1; //把上一行皇后的位置往后移一列
a[i] = INITIAL; //把上一行皇后的位置清除,重新探测
一、实验过程记录部分:
八皇后问题
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define QUEEN 8 //皇后的数目
#define INITIAL -10000 //棋盘的初始值
int a[QUEEN]; //一维数组表示棋盘
void init() //对棋盘进行初始化
2.十九世纪著名数学家高斯提出的八皇后问题求解,参见教材P154。
3.小偷行窃之0-1背包问题求解,实际例案数据可以自拟给出,参教材P156。
4.图的m着色问题*,参教材P160。
5.最优装载问题*,经销商/最小运输成本核算,拓扑特征数据可自拟给出。
6.不确定性问题*,彩票中奖概率事件等,实际问题自拟给出【*选做内容】。
实验设备(环境)及要求
微型计算机,visual C 6.0
实验内容
在视窗操作系统Windows XP/2003/20XX启动成功环境下,选择一个具体的需要回溯法搜索计算技术支持的实际问题,提出一个智能算法,并选择自己熟练掌握的计算机语言来编程,以达问题求解。实际问题(只选一个完成即可)如下:
1.给定有限n个城市及其连通图,并附加必要连线权值(如路程/交通费/速度/时间等值),整型数n=NZ,NZ={3,4,5…,Nm},Nm=max(NZ),求出每人旅行完n个城市所花最少时间或最少花费是多少,参教材P149/P164。