回溯法解八皇后问题

合集下载

八皇后问题

八皇后问题

八皇后问题:在国际象棋里面皇后可以横走,竖走,斜走。

我们现在有一个8*8的棋盘,怎样摆放8个皇后,而使彼此不冲突,也就是怎样使在同一行,同一列,斜对角线上只存在一个皇后。

解决办法:回溯法回溯法:回溯法有“通用的解题法”之称。

应用回溯法解问题时,首先应该明确问题的解空间。

一个复杂问题的解决往往由多部分构成,即,一个大的解决方案可以看作是由若干个小的决策组成。

很多时候它们构成一个决策序列。

解决一个问题的所有可能的决策序列构成该问题的解空间。

解空间中满足约束条件的决策序列称为可行解。

一般说来,解任何问题都有一个目标,在约束条件下使目标值达到最大(或最小)的可行解称为该问题的最优解。

在解空间中,前k 项决策已经取定的所有决策序列之集称为k 定子解空间。

0 定子解空间即是该问题的解空间。

C语言代码:#include<stdio.h>int count=0;/*计数*/int fit(int (*Q)[8],int i,int j)/*判断是否适合摆放皇后*/{int t,e;for(t=i,e=0;e<8;e++)if(Q[t][e]==1&&e!=j) return 0;/*pan duan hang*/for(e=j,t=0;t<8;t++)if(Q[t][e]==1&&t!=i) return 0 ;/*pan duan lie*/for(e=j,t=i;e>0&&t>0;e--,t--)/*pan duan left up */if(Q[t][e]==1) return 0;for(e=j,t=i;e<8&&t<8;e++,t++)if(Q[t][e]==1) return 0; /*pan duan right down*/for(e=j,t=i;e<8&&t>0;e++,t--)if(Q[t][e]==1) return 0;/*pan duan right up*/for(e=j,t=i;e>0&&t<8;e--,t++)if(Q[t][e]==1) return 0;/*pan duan left down*/return 1;/*if all the conditions are the wrong ,then we will get 1 ,so the queenfunction will be told to make the Q[i][j]=1.we will put a queen on Q[i][j].*/}void queen(int (*Q)[8],int j)/*求8皇后问题的解*/{ int i,k;if(j==8)/*递归判断,当j=8,说明Q【】【7】中摆放了皇后,所以得到一个解*/{for(i=0;i<8;i++){for(k=0;k<8;k++)printf(" %d",Q[i][k]);/*统计摆放的种类,以及输出结果;*/printf("\n");}printf("\n");count++;return;}for(i=0;i<8;i++){if(fit(Q,i,j)>0)/*在生成解空间树的同时进行深度搜索,从而实现减枝*/{Q[i][j]=1;queen(Q,j+1);Q[i][j]=0;/*进行回溯,因为每次会形成不同的基点,然后沿着各基点进行深度搜索,所以每次搜索完要回到例外基点,所以前面搜索的基点必然要归为零*/}}}main(){int Q[8][8],i,j;for(i=0;i<8;i++)for(j=0;j<8;j++)Q[i][j]=0;queen(Q,0);printf("%d",count);}运行的部分结果:。

八皇后问题(经典算法-回溯法)

八皇后问题(经典算法-回溯法)

⼋皇后问题(经典算法-回溯法)问题描述:⼋皇后问题(eight queens problem)是⼗九世纪著名的数学家⾼斯于1850年提出的。

问题是:在8×8的棋盘上摆放⼋个皇后,使其不能互相攻击。

即任意两个皇后都不能处于同⼀⾏、同⼀列或同⼀斜线上。

可以把⼋皇后问题扩展到n皇后问题,即在n×n的棋盘上摆放n个皇后,使任意两个皇后都不能互相攻击。

思路:使⽤回溯法依次假设皇后的位置,当第⼀个皇后确定后,寻找下⼀⾏的皇后位置,当满⾜左上、右上和正上⽅向⽆皇后,即矩阵中对应位置都为0,则可以确定皇后位置,依次判断下⼀⾏的皇后位置。

当到达第8⾏时,说明⼋个皇后安置完毕。

代码如下:#include<iostream>using namespace std;#define N 8int a[N][N];int count=0;//判断是否可放bool search(int r,int c){int i,j;//左上+正上for(i=r,j=c; i>=0 && j>=0; i--,j--){if(a[i][j] || a[i][c]){return false;}}//右上for(i=r,j=c; i>=0 && j<N; i--,j++){if(a[i][j]){return false;}}return true;}//输出void print(){for(int i=0;i<N;i++){for(int j=0;j<N;j++){cout<<a[i][j]<<" ";}cout<<endl;}}//回溯法查找适合的放法void queen(int r){if(r == 8){count++;cout<<"第"<<count<<"种放法\n";print();cout<<endl;return;}int i;for(i=0; i<N; i++){if(search(r,i)){a[r][i] = 1;queen(r+1);a[r][i] = 0;}}}//⼊⼝int main(){queen(0);cout<<"⼀共有"<<count<<"放法\n"; return 0;}。

回溯算法与八皇后问题N皇后问题Word版

回溯算法与八皇后问题N皇后问题Word版

回溯算法与八皇后问题(N皇后问题)1 问题描述八皇后问题是数据结构与算法这一门课中经典的一个问题。

下面再来看一下这个问题的描述。

八皇后问题说的是在8*8国际象棋棋盘上,要求在每一行放置一个皇后,且能做到在竖方向,斜方向都没有冲突。

更通用的描述就是有没有可能在一张N*N的棋盘上安全地放N个皇后?2 回溯算法回溯算法也叫试探法,它是一种系统地搜索问题的解的方法。

回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试。

在现实中,有很多问题往往需要我们把其所有可能穷举出来,然后从中找出满足某种要求的可能或最优的情况,从而得到整个问题的解。

回溯算法就是解决这种问题的“通用算法”,有“万能算法”之称。

N皇后问题在N增大时就是这样一个解空间很大的问题,所以比较适合用这种方法求解。

这也是N皇后问题的传统解法,很经典。

下面是算法的高级伪码描述,这里用一个N*N的矩阵来存储棋盘:1) 算法开始, 清空棋盘,当前行设为第一行,当前列设为第一列2) 在当前行,当前列的位置上判断是否满足条件(即保证经过这一点的行,列与斜线上都没有两个皇后),若不满足,跳到第4步3) 在当前位置上满足条件的情形:在当前位置放一个皇后,若当前行是最后一行,记录一个解;若当前行不是最后一行,当前行设为下一行, 当前列设为当前行的第一个待测位置;若当前行是最后一行,当前列不是最后一列,当前列设为下一列;若当前行是最后一行,当前列是最后一列,回溯,即清空当前行及以下各行的棋盘,然后,当前行设为上一行,当前列设为当前行的下一个待测位置;以上返回到第2步4) 在当前位置上不满足条件的情形:若当前列不是最后一列,当前列设为下一列,返回到第2步;若当前列是最后一列了,回溯,即,若当前行已经是第一行了,算法退出,否则,清空当前行及以下各行的棋盘,然后,当前行设为上一行,当前列设为当前行的下一个待测位置,返回到第2步;算法的基本原理是上面这个样子,但不同的是用的数据结构不同,检查某个位置是否满足条件的方法也不同。

数据结构与算法中的“递归”——用回溯法求解8皇后问题

数据结构与算法中的“递归”——用回溯法求解8皇后问题

八皇后问题是一个古老而著名的问题,它是回溯算法的典型例题。

该问题是十九世纪德国著名数学家高斯于1850年提出的:在8行8列的国际象棋棋盘上摆放着八个皇后。

若两个皇后位于同一行、同一列或同一对角线上,则称为它们为互相攻击。

在国际象棋中皇后是最强大的棋子,因为它的攻击范围最大,图6-15显示了一个皇后的攻击范围。

图6-15 皇后的攻击范围现在要求使这八个皇后不能相互攻击,即任意两个皇后都不能处于同一行、同一列或同一对角线上,问有多少种摆法。

高斯认为有76种方案。

1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。

现代教学中,把八皇后问题当成一个经典递归算法例题。

图6-16显示了两种八个皇后不相互攻击的情况。

图6-16八个皇后不相互攻击的情况现在来看如何使用回溯法解决八皇后问题。

这个算法将在棋盘上一列一列地摆放皇后直到八个皇后在不相互攻击的情况下都被摆放在棋盘上,算法便终止。

当一个新加入的皇后因为与已经存在的皇后之间相互攻击而不能被摆在棋盘上时,算法便发生回溯。

一旦发生这种情况,就试图把最后放在棋盘上的皇后移动到其他地方。

这样做是为了让新加入的皇后能够在不与其它皇后相互攻击的情况下被摆放在棋盘的适当位置上。

例如图6-17所示的情况,尽管第7个皇后不会与已经放在棋盘上的任何一皇后放生攻击,但仍然需要将它移除并发生回溯,因为无法为第8个皇后在棋盘上找到合适的位置。

图6-17 需要发生回溯的情况算法的回溯部分将尝试移动第7个皇后到第7列的另外一点来为第8个皇后在第8列寻找一个合适的位置。

如果第7个皇后由于在第7列找不到合适的位置而无法被移动,那么算法就必须去掉它然后回溯到第6列的皇后。

最终算法不断重复着摆放皇后和回溯的过程直到找到问题的解为止。

下面给出了求解八皇后问题的示例程序。

#include <conio.h>#include <iostream>using namespace std;// 首先要求皇后不冲突,那么每行只应该有一个皇后// 用queens[]数组在存储每个皇后的位置// 例如: queens[m] = n 表示第m行的皇后放在第n列上#define MAX 8int sum = 0;class QueenPuzzle{int queens[MAX]; // 存储每行皇后的列标public:void printOut(); // 打印结果int IsValid(int n); //判断第n个皇后放上去之后,是否合法 void placeQueen(int i); // 递归算法放置皇后};void QueenPuzzle::printOut(){for(int i=0; i<MAX; i++){for(int j=0; j<MAX; j++){if(j == queens[i])cout << "Q ";elsecout << "0 ";}cout << endl;}cout << endl << "按q键盘退出,按其他键继续" << endl << endl;if(getch() == 'q')exit(0);}// 在第i行放置皇后void QueenPuzzle::placeQueen(int i){for(int j=0; j<MAX; j++){// 如果全部放完了输出结果if(i == MAX){sum ++;cout << "第" << sum << "组解:" << endl;printOut();return;}// 放置皇后queens[i] = j;// 此位置不能放皇后继续试验下一位置if(IsValid(i))placeQueen(i+1);}}//判断第n个皇后放上去之后,是否合法,即是否无冲突int QueenPuzzle::IsValid(int n){//将第n个皇后的位置依次于前面n-1个皇后的位置比较。

八皇后问题--回溯解析

八皇后问题--回溯解析

八皇后问题--回溯解析/************************************************************** **********//* 回溯算法回溯算法也叫试探法,它是一种系统地搜索问题的解的方法。

二. 用回溯算法解决问题的一般步骤:1 针对所给问题,定义问题的解空间,它至少包含问题的一个(最优)解。

2 确定易于搜索的解空间结构,使得能用回溯法方便地搜索整个解空间。

3 以深度优先的方式搜索解空间,并且在搜索过程中用剪枝函数避免无效搜索。

问题的解空间通常是在搜索问题解的过程中动态产生的,这是回溯算法的一个重要特性。

确定了解空间的组织结构后,回溯法就从开始结点(根结点)出发,以深度优先的方式搜索整个解空间。

这个开始结点就成为一个活结点,同时也成为当前的扩展结点。

在当前的扩展结点处,搜索向纵深方向移至一个新结点。

这个新结点就成为一个新的活结点,并成为当前扩展结点。

如果在当前的扩展结点处不能再向纵深方向移动,则当前扩展结点就成为死结点。

此时,应往回移动(回溯)至最近的一个活结点处,并使这个活结点成为当前的扩展结点。

回溯法即以这种工作方式递归地在解空间中搜索,直至找到所要求的解或解空间中已没有活结点时为止。

回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试。

八皇后问题就是回溯算法的典型,第一步按照顺序放一个皇后,然后第二步符合要求放第2个皇后,如果没有符合位置符合要求,那么就要改变第一个皇后的位置,重新放第2个皇后的位置,直到找到符合条件的位置就可以了.回溯在迷宫搜索中使用很常见,就是这条路走不通,然后返回前一个路口,继续下一条路。

回溯算法说白了就是穷举法。

不过回溯算法使用剪枝函数,剪去一些不可能到达最终状态(即答案状态)的节点,从而减少状态空间树节点的生成。

回溯法是一个既带有系统性又带有跳跃性的的搜索算法。

它在包含问题的所有解的解空间树中,按照深度优先的策略,从根结点出发搜索解空间树。

八皇后以及N皇后问题分析

八皇后以及N皇后问题分析

⼋皇后以及N皇后问题分析⼋皇后是⼀个经典问题,在8*8的棋盘上放置8个皇后,每⼀⾏不能互相攻击。

因此拓展出 N皇后问题。

下⾯慢慢了解解决这些问题的⽅法:回溯法:回溯算法也叫试探法,它是⼀种系统地搜索问题的解的⽅法。

回溯算法的基本思想是:从⼀条路往前⾛,能进则进,不能进则退回来,换⼀条路再试。

在现实中,有很多问题往往需要我们把其所有可能穷举出来,然后从中找出满⾜某种要求的可能或最优的情况,从⽽得到整个问题的解。

回溯算法就是解决这种问题的“通⽤算法”,有“万能算法”之称。

N皇后问题在N增⼤时就是这样⼀个解空间很⼤的问题,所以⽐较适合⽤这种⽅法求解。

这也是N皇后问题的传统解法,很经典。

算法描述:1. 算法开始,清空棋盘。

当前⾏设为第⼀⾏,当前列设为第⼀列。

2. 在当前⾏,当前列的判断放置皇后是否安全,若不安全,则跳到第四步。

3. 在当前位置上满⾜条件的情况: 在当前位置放⼀个皇后,若当前⾏是最后⼀⾏,记录⼀个解; 若当前⾏不是最后⼀⾏,当前⾏设为下⼀⾏,当前列设为当前⾏的第⼀个待测位置; 若当前⾏是最后⼀⾏,当前列不是最后⼀列,当前列设为下⼀列; 若当前⾏是最后⼀⾏,当前列是最后⼀列,回溯,即清空当前⾏以及以下各⾏的棋盘,然后当前⾏设为上⼀⾏,当前列设为当前⾏的下⼀个待测位置; 以上返回第⼆步。

4.在当前位置上不满⾜条件: 若当前列不是最后⼀列,当前列设为下⼀列,返回到第⼆步; 若当前列是最后⼀列,回溯,即,若当前⾏已经是第⼀⾏了,算法退出,否则,清空当前⾏以及以下各⾏的棋盘,然后,当前⾏设为上⼀⾏,当前列设为当前⾏的下⼀个待测位置,返回第⼆步。

如何判断是否安全:把棋盘存储为⼀个N维数组a[N],数组中第i个元素的值代表第i⾏的皇后位置,这样便可以把问题的空间规模压缩为⼀维O(N),在判断是否冲突时也很简单, ⾸先每⾏只有⼀个皇后,且在数组中只占据⼀个元素的位置,⾏冲突就不存在了, 其次是列冲突,判断⼀下是否有a[i]与当前要放置皇后的列j相等即可。

回溯法解决N皇后问题C语言

回溯法解决N皇后问题C语言

回溯法解决N皇后问题C语⾔问题描述:⼋皇后问题是⼀个以国际象棋为背景的问题:如何能够在 8×8 的国际象棋棋盘上放置⼋个皇后,使得任何⼀个皇后都⽆法直接吃掉其他的皇后?为了达到此⽬的,任两个皇后都不能处于同⼀条横⾏、纵⾏或斜线上。

回溯法:回溯法⼜称试探法。

回溯法的基本做法是深度优先搜索。

即从⼀条路往前⾛,能进则进,不能进则退回来,换⼀条路再试。

源代码:#include<stdio.h>#include<math.h>int x[9]={0};bool PLACE(int k)//检测第k个皇后能否放进棋盘{int i=1;while(i<k){if(x[i]==x[k]||fabs(x[i]-x[k])==fabs(i-k))return false;i++;}return true;}void NQUEENS(int n){int i,k=1; //k为当前⾏号x[1]=0;//x[k]为第k⾏皇后所放的列号while(k>0){x[k]++;while(x[k]<=n&&!PLACE(k))//该⾏不符合,则放⼊下⼀⾏x[k]++;if(x[k]<=n){if(k==n)//输出x[]{for(i=1;i<=n;i++)printf("x[%d]:%d ",i,x[i]);printf("\n");}else//判断下⼀⾏{k++; x[k]=0;}}else k--;//没找到,则回溯}return ;}int main(){NQUEENS(8);return0;}。

八皇后问题——回溯法(pythonJAVA)

八皇后问题——回溯法(pythonJAVA)

⼋皇后问题——回溯法(pythonJAVA)⼋皇后问题,是⼀个古⽼⽽著名的问题,问题如下:在8×8格的国际象棋上摆放⼋个皇后,使其不能互相攻击,即任意两个皇后都不能处于同⼀⾏、同⼀列或同⼀斜线上,问有多少种摆法。

上边是⼀个8*8的国际棋盘,可以看到棋盘中的每个格⼦都标有数字。

每个数字都是两位,⼗位数字表⽰该格⼦所在的⾏,⽽个位数字表⽰该格⼦所在的列。

这样不难发现,处在同⼀⾏的两个格⼦其⼗位数都相同,处在同⼀列的两个格⼦其个位数都相同,处在同⼀斜线的两个格⼦有:|两个数字个位数的差|=|两个数字⼗位数的差|。

主要的三个限制条件明⽩了,接下来我们选择⼀种数据结构对“皇后”进⾏存储。

很明显,我们可以选择⼆维数组。

但是还可以选择⼀维数组。

在这⾥我们选择⼀维数组。

为什么选择⼀维数组呢?1.因为⼀⾏只放⼀个皇后,很符合我们⼀维数组的存放特性,即⼀个索引对应⼀个元素。

2.相对于⼆维数组,⼀位数组⽐较简单,更适合初学者。

我们以皇后所在的⾏标作为⼀位数组的索引,皇后所在的列标作为该索引对应的元素,例如arr[3]=5,代表第三⾏的皇后在第五列。

下边我们以python以及JAVA为例来解决这个问题。

num=0def eight_queen(arr,finish_line=0):if finish_line == len(arr): #如果放置皇后成功的⾏数与数组中的元素个数⼀致(即棋盘的⾏数)则认为完成了⼀种摆法global num #将上边定义的num定义为全局变量这样才能在后边对其进⾏⾃加操作num+=1print("第%s种摆法:" % num)for i in range(8):print((i,arr[i]))return# breakfor stand in range(len(arr)): #对整个列进⾏扫描,将列标的标号赋值给数组中对应的元素arr[finish_line] = standflag = Truefor line in range(finish_line):if arr[line] == stand or abs(arr[line]-stand) == finish_line-line: #有皇后与当前放置的皇后处于同⼀列或同⼀斜线上flag = False# stand-=1if flag==True:eight_queen(arr,finish_line+1)if__name__ == '__main__':eight_queen([None]*8)if num != 0:print("⼀共有%s种摆法" % num)else:print("⽆解")对于初学者理解可能不是特别轻松,所以在这⾥我们总结⼀个的定式,再遇到此类问题时直接套⽤以下定式即可。

数据结构课程设计 回溯法解决8皇后n皇后问题

数据结构课程设计 回溯法解决8皇后n皇后问题

数据结构课程设计学院:信息科学技术学院专业:电子信息工程(1)姓名:谢后乐学号:20101601310015N皇后问题N皇后问题:在n×n格的棋盘上放置彼此不受攻击的n个皇后。

按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。

n后问题等价于再n×n的棋盘上放置n个皇后,任何2个皇后不妨在同一行或同一列或同一斜线上。

回溯法简介:回溯法(探索与回溯法)是一种选优搜索法,按选优条件向前搜索,以达到目标。

但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。

我们发现,对于许多问题,所给定的约束集D具有完备性,即i元祖(x1,x2,…,xi)满足D中仅涉及到x1,x2,…,xi的所有约束意味着j(j<=i)元组(x1,x2,…)一定也满足D中仅涉及到x1,x2,…,的所有约束,i=1,2,…,n。

换句话说,只要存在0≤j≤n-1,使得(x1,x2,…,)违反D中仅涉及到x1,x2,…,的约束之一,则以(x1,x2,…,)为前缀的任何n元组(x1,x2,…,j+1,…,)一定也违反D中仅涉及到x1,x2,…,xi的一个约束,n≥i≥j。

因此,对于约束集D具有完备性的问题P,一旦检测断定某个j元组(x1,x2,…)违反D中仅涉及x1,x2,…,的一个约束,就可以肯定,以(x1,x2,…)为前缀的任何n元组(x1,x2,…,)都不会是问题P的解,因而就不必去搜索它们、检测它们。

回溯法正是针对这类问题,利用这类问题的上述性质而提出来的比枚举法效率更高的算法。

空间树回溯法首先将问题P的n元组的状态空间E表示成一棵高为n的带权有序树T,把在E中求问题P的所有解转化为在T中搜索问题P的所有解。

树T类似于检索树,它可以这样构造:设Si中的元素可排成xi(1) ,xi(2) ,...,xi(mi-1) ,|Si| =mi,i=1,2,...,n。

八皇后问题的解决方案

八皇后问题的解决方案

算法总结
3
解决八皇后问题常用算法
3.1
枚举法解决八皇后问题
3.2
非递归回溯法解决八皇后问题
3.3
递归回溯法解决八皇后问题
3.0
八皇后问题约束条件
a( i ) 1 2 3 4 5 6 7 8 a( 1) 2 0 -1 3 -2 4 -3 5 -4 6 -5 7 -6 8 -7 9
a( 2 ) a( 3 ) a( 4) a( 5 ) a( 6) a( 7 ) a( 8)
9 3 10 2 11 1 12 0 13 -1 14 -2
9 5 10 4 11 3 12 2 13 1 14 0 15 -1
9 7 10 6 11 5 12 4 13 3 14 2 15 1 16 0
3.0
八皇后问题约束条件
a( i ) =j 第i行j列放置皇后
判断不同列 a(i)≠a(j) 判断不同对角线 i-a(i)≠j-a(j) 判断不同反对角线 i+a(i)≠j+a(j)
取下一个………………
取下一个q (1)
用语言编程
For q1 = 1 To 8 For q2 = 1 To 8 For q3 = 1 To 8 For q4 = 1 To 8 For q5 = 1 To 8 For q6 = 1 To 8 For q7 = 1 To 8 For q8 = 1 To 8 q(q1) = q1 : q(q2) = q2 : q(q3) = q3 : q(q4) = q4 q(q5) = q5 : q(q6) = q6 : q(q7) = q7 : q(q8) = q8 If putdown(q)=1 Then printstr(q) Next q8 Next q7 Next q6 Next q5 Next q4 Next q3 Next q2 Next q1

C语言回溯法解八皇后问题(八皇后算法)

C语言回溯法解八皇后问题(八皇后算法)

C语⾔回溯法解⼋皇后问题(⼋皇后算法)⼋皇后问题(N皇后问题)的回溯法求解⼀、问题描述在⼀个国际象棋棋盘上放置⼋个皇后,使得任何两个皇后之间不相互攻击,求出所有的布棋⽅法,并推⼴到N皇后情况。

⼆、参考资料啥⽂字都不⽤看,B站上有个⾮常详细的动画视频解说,上链接三、源代码#include<iostream>#include<vector>#include<string>using namespace std;void put_queen(int x, int y, vector<vector<int>>&attack){//实现在(x,y)放置皇后,对attack数组更新,xy表⽰放置皇后的坐标,attack表⽰是否可以放置皇后//⽅向数组,⽅便后⾯对8个⽅向进⾏标记static const int dx[] = { -1,-1,-1,0,0,1,1,1 };static const int dy[] = { -1,0,1,-1,1,-1,0,1 };attack[x][y] = 1;//将皇后位置标记为1//通过两层for循环,将该皇后可能攻击到的位置标记for (int i = 1; i < attack.size(); i++)//从皇后位置向1到n-1个距离延伸{for (int j = 0; j < 8; j++)//遍历8个⽅向{int nx = x + i * dx[j];//⽣成的新位置⾏int ny = y + i * dy[j];//⽣成的新位置列//在棋盘范围内if (nx >= 0 && nx < attack.size() && ny >= 0 && ny < attack.size())attack[nx][ny] = 1;//标记为1}}}//回溯算法//k表⽰当前处理的⾏//n表⽰n皇后问题//queen存储皇后的位置//attack标记皇后的攻击范围//solve存储N皇后的全部解法void backtrack(int k, int n, vector<string>& queen,vector<vector<int>>& attack,vector<vector<string>>& solve){if (k == n)//找到⼀组解{solve.push_back(queen);//将结果queen存储⾄solvereturn;}//遍历0⾄n-1列,在循环中,回溯试探皇后可放置的位置for (int i = 0; i < n; i++){if (attack[k][i] == 0)//判断当前k⾏第i列是否可以放置皇后{vector<vector<int>> tmp = attack;//备份attack数组queen[k][i] = 'Q';//标记该位置为Qput_queen(k, i, attack);//更新attack数组backtrack(k + 1, n, queen, attack, solve);//递归试探k+1⾏的皇后的位置attack = tmp;//恢复attack数组queen[k][i] = '.';//恢复queen数组}}}vector<vector<string>>solveNQueens(int n){//string存储具体的摆放位置,<vector<string>>存放⼀种解法,⼆维vector存放全部解法vector<vector<string>>solve;//存储最后结果vector<vector<int>>attack;//标记皇后的攻击位vector<string>queen;//保存皇后位置//使⽤循环初始化attack和queen数组for (int i = 0; i < n; i++){attack.push_back((vector<int>()));for (int j = 0; j < n; j++){attack[i].push_back(0);}queen.push_back("");queen[i].append(n, '.');}backtrack(0, n, queen, attack, solve);return solve;//返回结果数组}int main(){//int num;//cin >> num;//输⼊皇后数初始化attack数组//vector<vector<int>> attack(num,vector<int>(num, 0));初始化queen数组//string s;//for (int i = 0; i < num; i++)s += '.';//vector<string> queen(num, s);int n;cin >> n;vector<vector<string>>result;result = solveNQueens(n);cout << n << "皇后共有" << result.size() << "种解法" << endl;for (int i = 0; i < result.size(); i++){cout << "解法" << i + 1 << ":" << endl;for (int j = 0; j < result[i].size(); j++){cout << result[i][j] << endl;}cout << endl;}system("pause");return 0;}四、测试结果四皇后⼋皇后到此这篇关于C语⾔回溯法解⼋皇后问题的⽂章就介绍到这了。

基本算法4-回溯法-N皇后问题

基本算法4-回溯法-N皇后问题

1
x1=1 2
x2= 2 3 kill
1
1 2
回溯到结点2生成结点8, 路径变为(1, 3), 则结点8成为E-结点, 它生成结点9和结点11都会被杀死(即它的儿子表示不可能导 x1=1 致答案的棋盘格局), 所以结点8也被杀死, 应回溯.
1
1
1
2
2
3
x2= 2 x2= 3 3 kill 8 x3=2 9 kill x3=4 11 kill
借书问题 [问题描述]
学校放暑假时,信息学辅导教师有n本书要分给参加培训的n个学生。如:A, B,C,D,E共5本书要分给参加培训的张、刘、王、李、孙5位学生,每人只能选 1本。教师事先让每个人将自己喜爱的书填写在如下的表中,然后根据他们填写的 表来分配书本,希望设计一个程序帮助教师求出可能的分配方案,使每个学生都满 意。 A 张 王 刘 孙 李 Y Y Y Y Y Y Y B C Y D Y E
● ●
……
● ● ● ● ● ● ● ●
……
……





● ● ● ●


● ●

● ●

● ●
● ● ● ●
● ● ● ●
● ● ● ●
● ● ● ● ●
● ● ●
•搜索解空间,剪枝:
– (1) 从空棋盘起,逐行放置棋子。
– (2) 每在一个布局中放下一个棋子,即推演到一 个新的布局。 – (3) 如果当前行上没有可合法放置棋子的位置, 则回溯到上一行,重新布放上一行的棋子。
61 2
64
3
16
3
20
4
22
1
25

5-4回溯法-皇后好累

5-4回溯法-皇后好累

要求在一个n×n的棋盘上放置n个皇后,使得她们彼此不受攻击。

八皇后问题求解过程第1列第2列第3列第4列第5列第6列第7列第1行第2行第3行第4行第5行第6行第7行第8行八皇后的一个可行解第1列第2列第3列第4列第5列第6列第7列第1行○第2行○第3行○第4行第5行○第6行○第7行○第8行○先回顾递归回溯法的一般形式:NTry(s)做挑选候选者的准备;while (未成功且还有候选者) {挑选下一个候选者next ;if (next 可接受) {记录next ;if (满足成功条件) {成功并输出结果}else Try(s+1);if (不成功) 删去next 的记录; }}return 成功与否}NTry(s){做挑选候选者的准备;while (未成功且还有候选者) {挑选下一个候选者next ;if (next 可接受) {记录next ;if (满足成功条件) {成功并输出结果}else Try(s+1);if (不成功) 删去next 的记录; }}return 成功与否}s 为准备放置后的行数候选者为1到n 列。

j = 0; q = 0; 令列标记j = 0;q 表示未成功。

列数不到n 就还有候选者(!q && j < n ) { 列数加1j++;各后都安全,便可接受(Safe(s, j)) {记下该行后的位置(列数)Record(s, j);n 行后都放完就成功了(s = = n) {q = 1; output( );} 不成功,删去后在该行的位置。

(!q) Move-Off(s, j); }}}q }数组B[n]表示棋盘。

若B[i]=j ,1≤i, j≤n ,表示棋盘的第i 行第j 列上有皇后。

N数组C[j]=1表示第j 列上无皇后,1≤j≤n 。

数组D[k]=1表示第k 条下行(↘)对角线上无皇后。

123456123456k = i + j ,2≤k≤2n 。

八皇后问题最简单算法

八皇后问题最简单算法

八皇后问题最简单算法
八皇后问题最简单算法是使用回溯法。

1. 回溯法在求解八皇后问题时,会生成一个8位的二进制数,每一位代表一列是否放置皇后。

如果某一列放置了皇后,则该位为1,否则为0。

2. 在放置皇后时,如果当前位置可以放置皇后,则尝试放置。

如果放置后当前位置形成了一个合法的棋盘,则继续递归地放置下一个皇后。

如果放置后形成了一个不合法的棋盘,则回溯到上一个状态,尝试其他位置。

3. 如果所有8个皇后都放置完毕,且形成了一个合法的棋盘,则找到了一个解。

以上信息仅供参考,如需了解更多信息,建议查阅八皇后问题相关书籍或咨询专业人士。

JS算法之八皇后问题(回溯法)

JS算法之八皇后问题(回溯法)

JS算法之⼋皇后问题(回溯法)⼋皇后这个经典的算法⽹上有很多种思路,我学习了之后⾃⼰实现了⼀下,现在⼤概说说我的思路给⼤家参考⼀下,也算记录⼀下,以免以后⾃⼰忘了要重新想⼀遍。

⼋皇后问题⼋皇后问题,是⼀个古⽼⽽著名的问题,是回溯算法的典型案例。

该问题是国际西洋棋棋⼿马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放⼋个皇后,使其不能互相攻击,即任意两个皇后都不能处于同⼀⾏、同⼀列或同⼀斜线上,问有多少种摆法。

⼯作原理⾸先从定义知道,两个皇后都不能处于同⼀⾏,所以第0个皇后放在第0⾏,第⼀个皇后放在第1⾏,以此类推。

先在第0⾏第0个格⼦(0,0)放⼀个皇后0,接着把处于同⼀⾏、同⼀列或同⼀斜线上的格⼦都标记为皇后0;然后把皇后1放到第1⾏标记为-1的格⼦中,以此类推直到放下皇后7(即最后⼀个皇后)。

若中途出现放皇后 iQueen时,第 iQueen⾏所有格⼦已经被全部标记,即if( arr[ iQueen*n + i ].index == -1 )的判断,则回溯到上⼀层函数(其实就是没有进⼊到if分⽀,所有没有进⾏递归了,代码执⾏完⾃然会跳回上⼀层函数继续执⾏)。

注意此时的执⾏环境(exection context)已经变了,所有setQueen函数内定义的变量全部回溯到上⼀层函数递归到下⼀层函数前的状态,即执⾏setQueen( iQueen + 1 );这⾏代码前的状态,例如递归前i=2,iQueen=1,⽆论下⼀层函数⾥的i和iQueen怎样变化,回溯后还是i=2,iQueen=1,然后紧接着执⾏未执⾏完的代码。

下⾯是执⾏顺序⼤概的图解:执⾏顺序:1.if-->1.1-->1.2-->1.递归-->2.if-->2.1-->2.2-->2.递归-->3.if-->2.回溯-->1.回溯(前⾯的标号表⽰第⼏层)var n = 8;//总⾏(列)数 8*8var iCount = 0;//n皇后的解法数//arr是长度为n*n的⼀维数组,保存着n*n个对象(li)并有各⾃的坐标,默认index都为-1,表⽰没有被任何皇后标记过 arr[ i*n + j ].y = i; arr[ i*n + j ].x = j;for(var i=0;i<n;i++){for(var j=0;j<n;j++){arr[ i*n + j ].x = j;arr[ i*n + j ].y = i;//arr[ i*n + j ].innerHTML = j + ',' + i;}}//iQueen从0开始,即皇后0function setQueen(iQueen){if( iQueen == n ){iCount++;console.log(iCount)return;}for(var i=0;i<n;i++){if( arr[ iQueen*n + i ].index == -1 ){arr[ iQueen*n + i ].index = iQueen;//arr[ iQueen*n + i ].innerHTML = iQueen;var x = arr[ iQueen*n + i ].x;var y = arr[ iQueen*n + i ].y;for(var j=0;j<arr.length;j++){if( arr[j].index == -1 && (arr[j].x == x || arr[j].y == y || arr[j].x - arr[j].y == x - y || arr[j].x + arr[j].y == x + y) ){arr[j].index = iQueen;//arr[j].innerHTML = iQueen;}}//执⾏到这⾥,就会跳到下⼀层函数中,在执⾏完下⼀层的函数后,才会回溯到上⼀层继续执⾏for循环(此时的for循环是上⼀层的for循环),包括后⾯的所有代码//需要注意的是,例如当前函数的iQueen=1,跳到下⼀层函数 iQueen=2,下⼀层函数执⾏完后,回溯到上⼀层,此时的执⾏环境已经是上⼀层的执⾏环境了,即iQueen是等于1,⽽不是等于2 //递归setQueen( iQueen + 1 );//回溯for(var j=0;j<arr.length;j++){if( arr[j].index == iQueen ){arr[j].index = -1;//arr[j].innerHTML = -1; }}}}}。

八皇后问题

八皇后问题
void Output()
{
int i;
//!输出序号。
printf("No.%-5d" , ++iCount);
//!依次输出各个列上的皇后的位置,即所在的行数。
for(i = 0 ; i < QUEENS ; i++)
printf("%d " , Site[i]);
for(j=0;j<8;j++)
{
Result += N_Queens(i,j,Queens+1);
if(Result>0)
br0)
return 1;
else
{
Chessboard[LocX][LocY] = 'X';
for(i = 1 ; i <= QUEENS ; i++)
{
//!在该列的第i行上放置皇后。
Site[n] = i;
//!如果放置没有冲突,就开始下一列的试探。
if(IsValid(n))
for(i=0;i<8;i++)
for(j=0;j<8;j++)
{
if(Chessboard[i][j] == 'Q')
printf("(%d,%d)n",i,j);
}
getch();
}
/*********************************************************
if(Chessboard[i--][j++] != 'X')

C++基于回溯法解决八皇后问题示例

C++基于回溯法解决八皇后问题示例

C++基于回溯法解决⼋皇后问题⽰例本⽂实例讲述了C++基于回溯法解决⼋皇后问题的⽅法。

分享给⼤家供⼤家参考,具体如下:回溯法的基本做法是搜索,或是⼀种组织得井井有条的,能避免不必要搜索的穷举式搜索法。

这种⽅法适⽤于解⼀些组合数相当⼤的问题。

回溯法在问题的解空间树中,按深度优先策略,从根结点出发搜索解空间树。

算法搜索⾄解空间树的任意⼀点时,先判断该结点是否包含问题的解。

如果肯定不包含,则跳过对该结点为根的⼦树的搜索,逐层向其祖先结点回溯;否则,进⼊该⼦树,继续按深度优先策略搜索。

回溯法指导思想——⾛不通,就掉头。

设计过程:确定问题的解空间;确定结点的扩展规则;搜索。

n皇后问题要在n*n的国际象棋棋盘中放n个皇后,使任意两个皇后都不能互相吃掉。

规则:皇后能吃掉同⼀⾏、同⼀列、同⼀对⾓线的任意棋⼦。

求所有的解。

n=8是就是著名的⼋皇后问题了。

设⼋个皇后为xi,分别在第i⾏(i=1,2,3,4……,8);问题的解状态:可以⽤(1,x1),(2,x2),……,(8,x8)表⽰8个皇后的位置;由于⾏号固定,可简单记为:(x1,x2,x3,x4,x5,x6,x7,x8);问题的解空间:(x1,x2,x3,x4,x5,x6,x7,x8),1≤xi≤8(i=1,2,3,4……,8),共88个状态;约束条件:⼋个(1,x1),(2,x2) ,(3,x3),(4,x4) ,(5,x5), (6,x6) , (7,x7), (8,x8)不在同⼀⾏、同⼀列和同⼀对⾓线上。

盲⽬的枚举算法:通过8重循环模拟搜索空间中的88个状态,从中找出满⾜约束条件的“答案状态”。

程序如下:/**作者:侯凯*说明:⼋皇后——盲⽬迭代法*⽇期:2013-12-18*/#include <iostream>using namespace std;bool check_1(int a[],int n){for(int i=2;i<=n;i++){for(int j=1;j<=i-1;j++){if ((a[i]==a[j])||(abs(a[i]-a[j])==i-j)){return false;}}}return true;//不冲突}void queens_1(){int a[9];int count = 0;for(a[1]=1;a[1]<=8;a[1]++){for(a[2]=1;a[2]<=8;a[2]++){for(a[3]=1;a[3]<=8;a[3]++){for(a[4]=1;a[4]<=8;a[4]++){for(a[5]=1;a[5]<=8;a[5]++){for(a[6]=1;a[6]<=8;a[6]++){for(a[7]=1;a[7]<=8;a[7]++){for(a[8]=1;a[8]<=8;a[8]++){if(!check_1(a,8))continue;else{for(int i=1;i<=8;i++){cout<<a[i];}cout<<endl;count++;}}}}}}}}}cout<<count<<endl;}void main(){queens_1();}程序思想⽐较简单,最后可知共92种摆放⽅法。

回溯法实现8皇后问题

回溯法实现8皇后问题

实验题目回溯法实现8皇后问题实验要求 a.掌握递归回溯算法的基本思想。

b.学习掌握应用面向对象通用回溯程序框架解决实际问题。

提高面向对象编程的技能。

实验内容(问题描述、算法设计、算法效率)回溯法实现8皇后问题a.问题描述:在n*n格的棋盘上放置彼此不受攻击的n个皇后。

按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。

N后问题等价于在n*n格的棋盘上放置n个皇后,任何2个皇后不放在同一行或同一列或同一斜线上。

b.算法设计:用n元组x[1;n]表示n后问题的解。

其中,x[i]表示皇后i放置在棋盘的第i行的第x[i]列。

由于不容许将2个皇后放在同一列上,所以解向量中的x[i]互不相同。

2个皇后不能放在同一斜线上是问题的隐约束。

对于一般的n后问题,这一隐约束条件可以化成显约束的形式。

如果将n*n 格的棋盘看做二维方阵,其行号从上到下,列号从左到右依次编号为1,2,...n。

从棋盘左上角到右下角的主对角线及其平行线(即斜率为-1的各斜线)上,2个下标值的差(行号-列号)值相等。

同理,斜率为+1的每条斜线上,2个下标值的和(行号+列号)值相等。

因此,若2个皇后放置的位置分别是(i,j)和(k,l),且i-j = k -l 或i+j = k+l,则说明这2个皇后处于同一斜线上。

以上2个方程分别等价于i-k = j-l 和i-k =l-j。

由此可知,只要|i-k|=|l-j|成立,就表明2个皇后位于同一条斜线上。

用回溯法解n后问题,用完全n叉树表示解空间。

可行性约束Place剪去不满足行,列和斜线约束的子树。

下面的解n后问题的回溯法中,递归函数Backtrack(1)实现对整个解空间的回溯搜索。

Backtrack(i)搜索解空间中第i层子树。

类Queen的数据成员记录解空间中节点信息,以减少传给Backtrack的参数。

sum记录当前已找到的可行方案数。

在算法Backtrack中,当i>n是,算法搜索至叶节点,得到一个新的n皇后互不攻击放置方案,当前已找到的可行方案数sum增1。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
{ printf(" ");
fprintf(fp," ");
}
printf("%d\n", i);
fprintf(fp, "%d\n", i);
}
printf
(".......................................................\n");
fprintf(fp,
/*/
#include <stdio.h>
#include <math.h>
#define false 0
#define true 1
#define quesize 8
int gx[quesize+1];
int sum=0;
int place( int k );
void print( int a[] );
fprintf(fp,"the sum of the ways of queens:%d\n", sum);
printf("the sum of the ways of queens:%d\n", sum);
fclose(fp);
return 1;
}
/*/////////////////////////////////////////////////////////////////////
{
int i = 1;
while ( i < k )
{ if ( ( gx[i] == gx[k] ) || ( abs( gx[i] - gx[k] )==abs( i - k ) )
)
return (false);
i = i + 1;
}
return (true);
}
/*/////////////////////////////////////////////////////////////////////
///
Resove the ways of n queens
///////////////////////////////////////////////////////////////////////
/*/
void nqueens( int n )
{ int k = 1;
gx[1] = 0;
while ( k > 0 )
//
If a queen in k row and gx[k] column then return 1 else return 0
///////////////////////////////////////////////////////////////////////
*/
int place( int k )
"........................................................\n");
fprintf
(fp,".....................................................\n");
sum = sum + 1;
}
*/
void print( int a[] )
{ int i,j;
printf("The %dth\n", sum+1);
fprintf(fp, "The %dth\n", sum+1);
for ( i = 1; i <= quesize; i++ )
{
for ( j = 1;j <= a[i]; j++)
///////
/////Completed date: 2007.12 ////////
/////Version number: Turboc 2.0
////////
///////////////////////////////////////////////////////////////////////
void nqueens( int n );
FILE *fp;
int main( )
{
system("cls");
fp = fopen("outfile.txt", "w");
if(!fp){
printf("the file can't be opened!");
return 0;
}
nqueens( quesize );
{ gx[k] = gx[k] + 1;
while ( ( gx[k] <= n ) && ( !place(k) ) )
gx[k] = gx[k] + 1;
if ( gx[k] <= n )
if ( k == n ) print(gx);
else {k = k + 1; gx[k] = 0;}
else k = k - 1;
}
}
/*////////////////////////////////////////
//
Print the results into outfile and screen.
///////////////////////////////////////////////////////////////////////
/*/////////////////////////////////////////////////////////////////////
///
/////The programming is a complex problem about the ways of
queens.///////
/////Programmer: Luo Xiaochun
回溯法解八皇后问题
在N * N格的棋盘上放置彼此不受攻击的N个皇后。N个皇后问题等价于在N * N格的棋盘上放置N个皇后,任何2个皇后不在同一行或同一列或同一斜线上。当N等于8,就是著名的八皇后问题。
此问题是通过C语言程序编写的,在Turboc环境下完成实现的。输出结果见(输出结果。TXT文件)
详细代码为:
相关文档
最新文档