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

⼋皇后问题(经典算法-回溯法)问题描述:⼋皇后问题(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行的皇后都已确定后,我们 就找到了一种方案
check2 (int a[ ],int n)
queen21(例) 1 b加约束的枚举算法{//i多nt次i; 被调用,只是一重循环
{int a[9]; for (a[1]=1;a[1]<=8;a[1]++) for (a[2]=1;a[2]<=8;a[2]++)
八皇后问题
1
1八皇后问题背景 2盲目的枚举算法 3加约束的枚举算法 4回溯法及基本思想 5 回溯法应用 6八皇后问题的递归回溯算法 7八皇后问题的非递归回溯算法
2
【背景】 八皇后问题是一个以国际象棋为背
景的问题: 如何能够在 8×8 的国际象棋棋盘上
放置八个皇后,使得任何一个皇后都 无法直接吃掉其他的皇后?为了达到 此目的,任两个皇后都不能处于同一 条横行、纵行或斜线上。
for(a[8]=1;a[8]<=8;a[8]++) 此算法可读性很好,
{if (check(a,8)==0)continue; 体现了“回溯”。但
else for(i=1;i<=8;i+nt(a[i]); }
题,而不能解决任意
}}}}}}}
的n皇后问题。
18
2 回溯法应用-算法说明
按什么顺序去搜? 目标是没有漏网之鱼,尽量速度快。
5
2 【问题设计】盲目的枚举算法
a 盲目的枚举算法
通过8重循环模拟搜索空间中的88个状态;
按枚举思想,以DFS的方式,从第1个皇后在第1列开 始搜索,枚举出所有的“解状态”:
从中找出满足约束条件的“答案状态”。
八皇后问题

计算机科学与技术专业数据结构课程设计报告设计题目:八皇后问题目录1需求分析 (2)1.1功能分析 (2)1.2设计平台 (3)2概要设计 (3)2.1算法描述 (4)2.2算法思想 (5)2.3数据类型的定义 (5)3详细设计和实现 (6)3.1算法流程图 (6)3.2 主程序 (6)3.3 回溯算法程序 (7)4调试与操作说明 (9)4.1调试情况 (9)4.2操作说明 (9)5设计总结 (11)参考文献 (12)附录 (12)1需求分析1.1功能分析八皇后问题是一个古老而著名的问题,该问题是十九世纪著名的数学家高斯1850年提出的,并作了部分解答。
高斯在棋盘上放下了八个互不攻击的皇后,他还认为可能有76种不同的放法,这就是有名的“八皇后”问题。
在国际象棋中,皇后是最有权利的一个棋子;只要别的棋子在它的同一行或同一列或同一斜线(正斜线或反斜线)上时,它就能把对方棋子吃掉。
所以高斯提出了一个问题:在8*8的格的国际象棋上摆放八个皇后,使其不能相互攻击,即任意两个皇后都不能处于同一列、同一行、或同一条斜线上面,问共有多少种解法。
现在我们已经知道八皇后问题有92个解答。
1、本演示程序中,利用选择进行。
程序运行后,首先要求用户选择模式,然后进入模式。
皇后个数设0<n<11。
选择皇后个数后,进入子菜单,菜单中有两个模式可以选择。
2、演示程序以用户和计算机的对话方式执行,即在计算机终端上显示“提示信息”之后,由用户在键盘上输入演示程序中规定的运算命令:相应的输入数据和运算结果显示在其后。
3、程序执行的命令包括:1)进入主菜单。
2)选择皇后问题,输入是几皇后。
3)进入子菜单。
4)选择皇后显示模式。
5)选择结束4、测试数据1)N的输入为4;2)共有2个解答。
3)分别是○●○○○○●○○○○●●○○○●○○○○○○●○○●○○●○○1.2设计平台Windows2000以上操作系统;Microsoft Visual C++ 6.02概要设计问题:N后问题问题描述:国际象棋中皇后可以攻击所在行,列,斜线上的每一个位置,按照此规则要在一个n*n的棋盘上放n个皇后使每一个皇后都不互相攻击问题分析:引入1个数组模拟棋盘上皇后的位置引入3个工作数组行数组[k]=1,表示第k行没有皇后右高左低数组[k]=1,表示第k条右高左低的斜线上没有皇后左高右低数组[k]=1,表示第k条左高右低的斜线上没有皇后观察棋盘找到规律同一右高左低的斜线上的方格,它们的行号和列号之和相等;同一左高右低的斜线上的方格,它们的行号和列号只差相等;开始时,所有行和斜线上都没有皇后,从第一列的第一行配置第一个皇后开始,在第m列的皇后位置数组[m]行放置了一个合理的皇后之后,准备考察第m+1列时,在数组行数组[],右高左低数组[],左高右低数组[]中为第m列,皇后位置数组[m]的位置设定有皇后标志如果按此放置位置得不到结果,则把当前列中的有皇后标记改为无皇后标记。
数学游戏玩转数学棋盘游戏

数学游戏玩转数学棋盘游戏数学游戏:玩转数学棋盘游戏数学是一门既有挑战性又充满乐趣的学科。
而数学游戏则是一种将数学知识与娱乐元素相结合的方式,能够在玩耍的同时提高数学能力。
数学棋盘游戏就是其中之一,通过棋盘和棋子的摆放以及规则的设定,挑战玩家的数学思维能力和解题能力。
本文将为你介绍一些常见的数学棋盘游戏,并分享一些解题技巧和策略。
一、黑白棋黑白棋,又称翻转棋,是一种经典的二人对战游戏。
棋盘上有64个格子,棋子的正反面分别为黑和白。
棋子的翻转规则是:当一枚棋子被对方棋子夹在两枚自己的棋子之间时,就可以将对方的棋子翻转成自己的棋子。
游戏的目标是在棋盘被填满或无法进行合法移动时,拥有最多棋子的一方获胜。
解题技巧:1. 规避角落:角落的棋子最难被翻转,因此在游戏初期,应该尽量避免在角落放置自己的棋子,以免被对方夹住。
2. 占领边界:边界的棋子比较容易被翻转,因此在游戏的中期,应该尽量占领边界位置,增加自己的翻转机会。
3. 长远考虑:不要只追求眼前的翻转,要从长远来看,选择能够获得更多翻转机会的位置。
二、数独数独是一种基于数字逻辑的棋盘游戏。
游戏的目标是填写数字,确保每一行、每一列和每个九宫格内的数字都是1-9的不重复数字。
数独棋盘由一个9x9的方阵组成,部分格子内已经填有数字,玩家需要根据已知数字的限制,推断并填写剩余的数字。
解题技巧:1. 排除法:通过排除法,确定每个格子可填的数字范围。
首先,确定每个格子所在行、列、九宫格内已有数字,并将这些数字从候选数字中排除。
然后,根据唯一解的原则,确定可填数字范围最小的格子进行填写,然后循环以上步骤,直至填满整个数独棋盘。
2. 摒除法:将全部数字候选数填入数独格子中,逐个进行检查。
通过检查每个数字是否符合数独规则来排除不符合的数字,最终得到确定的数字填入。
三、八皇后八皇后是一种经典的布局问题。
规则是在一个8x8的棋盘上放置8个皇后,使得每个皇后都不能互相攻击。
皇后可以攻击与之在同一行、同一列或同一对角线上的其他棋子。
C++课程设计八皇后问题

安徽建筑工业学院数据结构设计报告书院系数理系专业信息与计算科学班级11信息专升本学号11207210138姓名李晓光题目八皇后指导教师王鑫1.程序功能介绍答:这个程序是用于解决八皇后问题的。
八皇后问题等于要求八个皇后中的任意两个不能被放在同一行或同一列或同一斜线上。
做这个课题,重要的就是先搞清楚哪个位置是合法的放皇后的位置,哪个不能,要先判断,后放置。
我的程序进入时会让使用者选择程序的功能,选【1】将会通过使用者自己手动输入第一个皇后的坐标后获得答案;选【2】将会让程序自动运算出固定每一个皇后后所有的排列结果。
2.课程设计要求答:(1)增加函数,完成每输入一组解,暂停屏幕,显示“按任意键继续!”。
(2)完善程序,编程计算八皇后问题共有集中排列方案。
(3)增加输入,显示在第一个皇后确定后,共有几组排列。
(4)将每组解的期盼横向排列输出在屏幕上,将五个棋盘并排排列,即一次8行同时输出5个棋盘,同样完成一组解后屏幕暂停,按任意键继续。
(5)求出在什么位置固定一个皇后后,解的数量最多,在什么位置固定皇后后,解的数量最少,最多的解是多少,最少的解是多少,并将最多,最少解的皇后位置及所有的解求出,同样5个一组显示。
3.对课程题目的分析与注释答:众所周知的八皇后问题是一个非常古老的问题,问题要求在一个8*8的棋盘上放上8个皇后,使得每一个皇后既攻击不到另外七个皇后,也不被另外七个皇后所攻击。
按照国际象棋的规则,一个皇后可以攻击与之处在同一行或同一列或同一斜线上的其他任何棋子。
因此,本课程设计的目的也是通过用C++语言平台在一个8*8的棋盘上放上8个皇后,使得每一个皇后既攻击不到另外七个皇后,也不被另外七个皇后所攻击的92种结构予以实现。
使用递归方法最终将其问题变得一目了然,更加易懂。
首先要用到类,将程序合理化:我编辑了一个盘棋8*8的类:class Board,还有个回溯法的类:class Stack,关键的类好了,然后编辑好类的成员,然后编辑主函数利用好这些类的成员,让其运算出结果。
八皇后问题有多少解

八皇后问题有多少解八皇后问题有92解。
皇后可以在横、竖、斜线上不限步数地吃掉其他棋子。
如何将8个皇后放在棋盘上(有8 * 8个方格),使它们谁也不能被吃掉!这就是著名的八皇后问题。
对于某个满足要求的8皇后的摆放方法,定义一个皇后串a与之对应,‘即a=b1b2…b8,其中bi为相应摆法中第i行皇后所处的列数。
已经知道8皇后问题一共有92组解(即92个不同的皇后串)。
给出一个数b,要求输出第b个串。
串的比较是这样的:皇后串x置于皇后串y之前,当且仅当将x视为整数时比y小。
//输入数据//第1行是测试数据的组数n,后面跟着n行输入。
每组测试数据占1行,包括一个正整数b(1 <= b <= 92)//输出要求//n行,每行输出对应一个输入。
输出应是一个正整数,是对应于b 的皇后串//输入样例//2//1//92//输出样例//15863724//84136275解题思路一因为要求出92种不同摆放方法中的任意一种,所以我们不妨把92种不同的摆放方法一次性求出来,存放在一个数组里。
为求解这道题我们需要有一个矩阵仿真棋盘,每次试放一个棋子时只能放在尚未被控制的格子上,一旦放置了一个新棋子,就在它所能控制的所有位置上设置标记,如此下去把八个棋子放好。
当完成一种摆放时,就要尝试下一种。
若要按照字典序将可行的摆放方法记录下来,就要按照一定的顺序进行尝试。
也就是将第一个棋子按照从小到大的顺序尝试;对于第一个棋子的每一个位置,将第二个棋子从可行的位置从小到大的顺序尝试;在第一第二个棋子固定的情况下,将第三个棋子从可行的位置从小到大的顺序尝试;依次类推。
首先,我们有一个8*8的矩阵仿真棋盘标识当前已经摆放好的棋子所控制的区域。
用一个有92行每行8个元素的二维数组记录可行的摆放方法。
用一个递归程序来实现尝试摆放的过程。
基本思想是假设我们将第一个棋子摆好,并设置了它所控制的区域,则这个问题变成了一个7皇后问题,用与8皇后同样的方法可以获得问题的解。
1213:八皇后问题

1213:⼋皇后问题【题⽬描述】在国际象棋棋盘上放置⼋个皇后,要求每两个皇后之间不能直接吃掉对⽅。
【输⼊】(⽆)【输出】按给定顺序和格式输出所有⼋皇后问题的解(见样例)。
【输⼊样例】(⽆)【输出样例】No. 11 0 0 0 0 0 0 00 0 0 0 0 0 1 00 0 0 0 1 0 0 00 0 0 0 0 0 0 10 1 0 0 0 0 0 00 0 0 1 0 0 0 00 0 0 0 0 1 0 00 0 1 0 0 0 0 0No. 21 0 0 0 0 0 0 00 0 0 0 0 0 1 00 0 0 1 0 0 0 00 0 0 0 0 1 0 00 0 0 0 0 0 0 10 1 0 0 0 0 0 00 0 0 0 1 0 0 00 0 1 0 0 0 0 0...以下省略解题分析:关键在于斜线还有是否访问过,正斜与反斜⾓的特点#include<bits/stdc++.h>using namespace std;int a[10001],b[10001],w[10001],m[10001],tot=0;int print(){tot++;cout<<"No. "<<tot<<endl;for(int j=1;j<=8;++j){for(int i=1;i<=8;++i)if(j==a[i])cout<<1<<" ";else cout<<0<<" ";cout<<endl;}}int search(int j){for(int i=1 ;i<=8;++i){if(b[i]==0&&w[i-j+7]==0&&m[i+j]==0){a[j]=i;b[i]=1;w[i-j+7]=1;m[i+j]=1;if(j==8) print();else search(j+1);b[i]=0;w[i-j+7]=0;m[i+j]=0;}}}int main(){search(1);return 0;}记住限制条件是该列有没访问过,还有斜⾓两个⽅向。
八皇后问题实验报告

软件工程上机报告实验名称:八皇后问题图形界面求解姓名:郭恂学号:2011011435班级:11级数学班中国石油大学(北京)计算机科学与技术系一、试验程序截图:点击显示下一组解即可显示下一组解:同样的,如果点击上一组解即可显示上一组解。
若在第1组解时点击显示上一组解会弹出报错提示框。
同样,若在第92组解点击显示下一组解也会弹出报错提示框:二、程序代码程序使用Java语言编写,编写环境为jdk1.6.0_18。
使用编程开发环境eclipse.exe编写。
本程序创建了两个类,两个类在同一个工程中。
其中Queen类的作用仅仅用来保存八皇后问题计算结果的数据,便于画图时使用。
本程序大概由两部分组成,第一部分是解八皇后问题,第二部分是画图。
程序源代码为:类1:public class Queen{public int[] x=new int[8];public int[] y=new int[8];public String name;}类2:import javax.swing.*;import java.awt.event.*;import java.awt.*;import javax.swing.JOptionPane;public class bahuanghou extends JFrame implements ActionListener {//JLabel[] l;int number=0; //当前显示的解的编号int sum=0; //所有解得数量JLabel l2;JButton b1,b2; //b1为显示下一组解得按钮,b2为显示上一组解得按钮。
Queen[] q=new Queen[128]; //得到的解储存在Queen类的数组里面。
private Image bomb1=Toolkit.getDefaultToolkit().getImage("D:\\qizi1.JPG"); //黑格棋子为bomb1private Image bomb2=Toolkit.getDefaultToolkit().getImage("D:\\qizi2.JPG"); //白格棋子为bomb2public bahuanghou() //构造方法,初始化窗口。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1.引子
中国有一句古话,叫做“不撞南墙不回头",生动的说明了一个人的固执,有点贬义,但是在软件编程中,这种思路确是一种解决问题最简单的算法,它通过一种类似于蛮干的思路,一步一步地往前走,每走一步都更靠近目标结果一些,直到遇到障碍物,我们才考虑往回走。
然后再继续尝试向前。
通过这样的波浪式前进方法,最终达到目的地。
当然整个过程需要很多往返,这样的前进方式,效率比较低下。
2.适用范围
适用于那些不存在简明的数学模型以阐明问题的本质,或者存在数学模型,但是难于实现的问题。
3.应用场景
在8*8国际象棋棋盘上,要求在每一行放置一个皇后,且能做到在竖方向,斜方向都没有冲突。
国际象棋的棋盘如下图所示:
4.分析
基本思路如上面分析一致,我们采用逐步试探的方式,先从一个方向往前走,能进则进,不能进则退,尝试另外的路径。
首先我们来分析一下国际象棋的规则,这些规则能够限制我们的前进,也就是我们前进途中的障碍物。
一个皇后q(x,y)能被满足以下条件的皇后
q(row,col)吃掉
1)x=row(在纵向不能有两个皇后)
2) y=col(横向)
3)col + row = y+x;(斜向正方向)
4) col - row = y-x;(斜向反方向)
遇到上述问题之一的时候,说明我们已经遇到了障碍,不能继续向前了。
我们需要退回来,尝试其他路径。
我们将棋盘看作是一个8*8的数组,这样可以使用一种蛮干的思路去解决这个问题,这样我们就是在8*8=64个格子中取出8个的组合,C(64,80) = 4426165368,显然这个数非常大,在蛮干的基础上我们可以增加回溯,从第0列开始,我们逐列进行,从第0行到第7行找到一个不受任何已经现有皇后攻击的位置,而第五列,我们会发现找不到皇后的安全位置了,前面四列的摆放如下:
第五列的时候,摆放任何行都会上图所示已经存在的皇后的攻击,这时候我们认为我们撞了南墙了,是回头的时候了,我们后退一列,将原来摆放在第四列的皇后(3,4)拿走,从(3,4)这个位置开始,我们再第四列中寻找下一个安全位置为(7,4),再继续到第五列,发现第五列仍然没有安全位置,回溯到第四列,此时第四列也是一个死胡同了,我们再回溯到第三列,这样前进几步,回退一步,最终直到在第8列上找到一个安全位置(成功)或者第一列已经是死胡同,但是第8列仍然没有找到安全位置为止
总结一下,用回溯的方法解决8皇后问题的步骤为:
1)从第一列开始,为皇后找到安全位置,然后跳到下一列
2)如果在第n列出现死胡同,如果该列为第一列,棋局失败,否则后退到上一列,在进行回溯
3)如果在第8列上找到了安全位置,则棋局成功。
8个皇后都找到了安全位置代表棋局的成功,用一个长度为8的整数数组queenList代表成功摆放的8个皇后,数组索引代表棋盘的col向量,而数组的值为棋盘的row向
量,所以(row,col)的皇后可以表示为(queenList[col],col),如上图中的几个皇后可表示为:
queenList[0] = 0; queenList[1] = 3; queenList[2] = 1; queenList[3] =
4; queenList = 2;
我们看一下如何设计程序:
首先判断(row,col)是否是安全位置的算法:
bool IsSafe(int col,int row,int[] queenList)
{
//只检查前面的列
for (int tempCol = 0; tempCol < col; tempCol++)
{
int tempRow = queenList[tempCol];
if (tempRow == row)
{
//同一行
return false;
}
if (tempCol == col)
{
//同一列
return false;
}
if (tempRow - tempCol == row - col || tempRow + tempCol == ro w + col)
{
return false;
}
}
return true;
}
设定一个函数,用于查找col列后的皇后摆放方法:
///<summary>
///在第col列寻找安全的row值
///</summary>
///<param name="queenList"></param>
///<param name="col"></param>
///<returns></returns>
public bool PlaceQueue(int[] queenList, int col)
{
int row = 0;
bool foundSafePos = false;
if (col == 8) //结束标志
{
//当处理完第8列的完成
foundSafePos = true;
}
else
{
while (row < 8 && !foundSafePos)
{
if (IsSafe(col, row, queenList))
{
//找到安全位置
queenList[col] = row;
//找下一列的安全位置
foundSafePos = PlaceQueue(queenList, col + 1);
if (!foundSafePos)
{
row++;
}
}
else
{
row++;
}
}
}
return foundSafePos;
}
调用方法:
static void Main(string[] args)
{
EightQueen eq = new EightQueen();
int[] queenList = new int[8];
for (int j = 0; j < 8; j++)
{
Console.WriteLine("-----------------"+j+"---------------------");
queenList[0] = j;
bool res = eq.PlaceQueue(queenList, 1);
if (res)
{
Console.Write(" ");
for (int i = 0; i < 8; i++)
{
Console.Write(" " + i.ToString() + " ");
}
Console.WriteLine("");
for (int i = 0; i < 8; i++)
{
Console.Write(" "+i.ToString()+" ");
for (int a = 0; a < 8; a++)
{
if (i == queenList[a])
{
Console.Write(" q ");
}
else
{
Console.Write(" * ");
}
}
Console.WriteLine("");
}
Console.WriteLine("---------------------------------------");
}
else
{
Console.WriteLine("不能完成棋局,棋局失败!");
}
}
Console.Read();
}
递归算法PlaceQueue,完成这样的功能:它寻找第col列后的皇后的安全摆放位置,如果该函数返回了false,表示当前进入了死胡同,需要进行回溯,直到为0-7列都找
到了安全位置或者找遍这些列都找不到安全位置的时候终止。
用递归算法解决8皇后问题的示例程序:
/Files/jillzhang/EightQueens.rar
欢迎大家下载;
-----------------------------------------------------------------------------------------------------------------
递归算法到这篇为止,已经学习到了分而治之,动态编程,回溯等重要思想,也用这些问题解决了一些具体问题,比如排序,背包,8皇后问题等,通过对理论的学习
和对实际问题的解决,充分理解递归算法的使用方法。
在编写学习系列的过程中,绝大多数都参考数据结构C++语言描述-应用标准模板库,特此感谢原书作者:。