八皇后问题

八皇后问题

*爱你&永不变心* 提交于 2020-01-22 08:38:29
八皇后问题 题目:在 8×8 的国际象棋棋盘上放置八个皇后,保证任何一个皇后都无法直接吃掉其他的皇后的情况下,即任意两个皇后都不能处于同一条横行、纵行或斜线上。一共有多少中摆放皇后的方法?(92种) 可以利用回溯+递归:有些类似于图的深度搜索,先找到一种方法,再在此方法上一步步回溯。 思路:用数组Queue[]的存储皇后的位置(下标+值),用数组column[]的下标代表是第几列,用column[]数组的值代表此列是否有皇后,用loblique[]和roblique[]存储左斜线和右斜线上是否有皇后;统一:0代表有皇后,1代表无皇后 同一斜列上,行数加列数是同一个常数或行数减列数是一个常数 步骤:1、初始化三个数组 2、for循环 3、递归回溯 # include <iostream> # include <string.h> # include <stdio.h> # define maxnum 8 int coun = 0 ; //记录八皇后摆放的方法数 int column [ maxnum + 1 ] ; int loblique [ maxnum * 2 + 1 ] , roblique [ maxnum * 2 + 1 ] ; //左斜列i+j从2~16,所以是maxnum*2+1;左斜列i-j从-7~7. int Queue [ maxnum + 1 ] ;

【算法复习二】八皇后问题 ---- 回溯

ⅰ亾dé卋堺 提交于 2020-01-20 08:42:50
一,问题描述 在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 二,分析 采用逐步试探的方式,先从一个方向往前走,能进则进,不能进则退并尝试另外的路径。首先我们来分析一下国际象棋的规则,这些规则能够限制我们的前进,也就是我们前进途中的障碍物。一个皇后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,8) = 4426165368,显然这个数非常大,在蛮干的基础上我们可以增加回溯,从第0列开始,我们逐列进行,从第0行到第7行找到一个不受任何已经现有皇后攻击的位置。 前面四列的摆放如上图则 第五列,我们会发现找不到皇后的安全位置 第五列 的时候,摆放任何行都会受到上图所示已经存在的皇后的攻击,这时候我们认为我们撞了南墙了,是回头的时候了,我们后退一列,将原来摆放在第四列的皇后 (3,4)拿走

python3 回溯法解决八皇后问题--详细解释

北城余情 提交于 2020-01-20 02:12:25
问题: 国际象棋棋盘是8 * 8的方格,每个方格里放一个棋子。皇后这种棋子可以攻击同一行或者同一列或者斜线(左上左下右上右下四个方向)上的棋子。在一个棋盘上如果要放八个皇后,使得她们互相之间不能攻击(即任意两两之间都不同行不同列不同斜线),求出一种(进一步的,所有)布局方式。 思路: (粘贴一波网上已有的递归思路,就不码字了)第一个需要解决的小问题就是,如何用数学的语言来表述斜线上重叠的皇后。其实我们可以看到,对于位于(i,j)位置的皇后而言,其四个方向斜线上的格子下标分别是 (i-n,j+n), (i-n,j-n), (i+n,j-n), (i+n,j+n)。当然i和j的±n都要在[0,7]的范围内,保持不越界。暂时抛开越界限制不管,这个关系其实就是: 目标格子(a,b)和本格子(i,j)在同一条斜线上 等价于 |a - i| == |b - j| 。 然后,从递归的思想来看,我们在从第一行开始给每一行的皇后确定一个位置。每来到新的一行时,对本行的所有可能位置(皇后放在这个位置和前面所有已放置的皇后无冲突)分别进行递归地深入;若某一行可能的位置数为0,则表明这是一条死路,返回上一层递归寻找其他办法;若来到的这一行是第九行(不存在第九行,只不过是说明前八行都已经正确配置,已经得到一个解决方案),这说明得到解决方案。 可以看到,寻找一行内皇后应该摆放的位置这是个递归过程

回溯算法之八皇后问题

坚强是说给别人听的谎言 提交于 2020-01-12 03:54:10
一、什么是回溯算法? 我们肯定都玩过迷宫游戏吧,比较复杂的迷宫,肯定是不可能第一遍就直接过了,只能一步一步地进行尝试。当走到一个死胡同时,只能退回到上一个分岔口进行重新选择。 数独游戏也是这样的,对于一个不确定的方格,我们就会先将这个方格可能出现的问题记录下来,一个一个地尝试,直到得到正确解。有着“通用解”称呼 所以,回溯算法就是类似于枚举的算法,将这一步的所以可能性一个一个地进行尝试。上边迷宫中的分岔口和数独中的可能出现多个数字的方格就是“回溯点” 二、有什么优缺点? 因为要对每一个点的可能情况都进行枚举测试,所以效率特别低,比如后边下边例子中的“八皇后问题”中,总共要进行15000次左右的运算,虽然对于计算机来说是很快的,但是更加复杂的问题,可能会更多 它可是有着“通用解”称呼,基本上大多数的这类问题都可以用此方法解决。 三、经典的“八皇后”问题 八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。计算机发明后,有多种计算机语言可以解决此问题。

数据结构和算法之八皇后问题

无人久伴 提交于 2019-12-28 03:54:40
一、问题描述 将八位皇后放在一张8*8的棋盘上,使得每位皇后都无法吃掉别的皇后。(即任意两个皇后都不在同一条横线,竖线,斜线上),求一共能有多少种摆放的方法。 二、图解问题描述 假设我们放入第一个皇后,位置再第五行第四列上,那么他的同一条横线,竖线,斜线上都不能放其他皇后,如下图 我们在空白处放入第二个皇后,比如位置:第四行第六列,如下图 如此下去,能放下一个皇后的位置会越来越少,能同时放下8个皇后的话,我们该如何设计每个皇后的位置呢?可以采取递归回溯的思想。 三、什么是递归回溯 1、概念 我个人总结为:不撞南墙不回头,撞了南墙才回头。 2、图解 为了方便,我就弄4x4的格子了,不搞8x8那么大了。 假设第一个皇后位置再第一行第一列,如下图 我们放入第二个皇后,假设位置为第二行第三列,如下图 这样一来前面两位皇后已经把第三行全部锁死了,唯一的空隙就是第四行第二列了,但是第三位皇后如果放到那里的话,第四位皇后就没地方放了,game over!所以我们只能返回上一步,来给第二位皇后换个位置(这种递归到最后发现走不通然后回头移动之前走过的棋子的套路就是回溯,也就是不撞南墙不回头,撞了南墙才回头)。 我们将第二个皇后后移一列(从原来的第二行第三列换成第二行第四列)再看效果,如下图 此时,第三个皇后有两个位置可以选择,目测效果不错,但实际不管你放到那两个位置的哪个位置上

经典算法之八皇后问题

橙三吉。 提交于 2019-12-25 09:06:16
八皇后问题是一个古老而又著名的问题,是学习回溯算法的一个经典案例。今天我们就一起来探究一下吧! 时间退回到1848年,国际西洋棋棋手马克斯·贝瑟尔提出了这样的一个问题, 在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问一共有多少种摆法。 后面陆续有不同的学者提出自己的见解。大数学家高斯认为一共有76种摆法,1854年在柏林的象棋杂志上不同的作者发表了共计40种不同的见解,后来还有人利用图论的方法得出共有92种摆法。 而如今,通过我们的计算机以及编程语言我们可以轻松的解决这个问题。 最直接的也是最容易想到的一种解法便是暴力法,我们可以在8×8的格子中任选8个皇后,选定后看是否满足任意两个皇后都不处于同行同列同斜线的条件,若满足则累计满足条件的方案。学习过排列组合的我们发现64取8这个数字达到了40亿,显然是令人难以接受的。 但我们根据这个条件,我们可以人为地做出一些选择,比如根据条件我们可知每行每列最多都只能有一个皇后,这样可以在一定程度上缩减问题的规模。在第一行的某一列选择放置一个皇后,共有8种不同的选择,而第二行只能选择剩下的7列,也就是7种选择,剩下每一行的选择都会递减1,那么总共可供选择的方案有8的阶乘种,已经是一种远优于暴力解法的解法,但是这个阶乘的时间复杂度恐怕也难以令人接受,还有更优的解法吗? 那是自然的

八皇后问题

耗尽温柔 提交于 2019-12-19 19:53:11
八皇后 问题。是一个古老而著名的问题。是 回溯算法 的典型案例。 该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击。即随意两个皇后都不能处于同一行、同一列或同一斜线上。问有多少种摆法。 高斯 觉得有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解。后来有人用图论的方法解出92种结果。 计算机发明后。有多种计算机语言能够解决此问题。 解题思路: 我们按行推断。从上到下,假设某个位置有效,则置“Q”。无效则置“.”。基本的问题就是推断该位置是否有效。是否是危急位置(会产生冲突)。我们要推断本行、本列、此斜线上都没有皇后存在,此时才干够在这个位置上放置皇后。代码例如以下: #include <iostream> #include <vector> #include <string> using namespace std; const int queenNum=8; int count=0; vector<vector<string> > solveNQueens(int n); void Nqueen(int row,int n,vector<vector<string>> &chess); bool notDanger(int row,int j,vector<vector<string>> chess)

回溯法解决八皇后问题

巧了我就是萌 提交于 2019-12-18 18:41:58
1.“八皇后”问题 八皇后问题是十九世纪著名数学家高斯于1850年提出的。问题是:在8*8的棋盘上摆放8个皇后,使其不能互相攻击,即任意的两个皇后不能处在同一行,同一列,或同一斜线上。可以把八皇后问题拓展为n皇后问题,即在n*n的棋盘上摆放n个皇后,使其任意两个皇后都不能处于同一行、同一列或同一斜线上。 2.冲突条件判断 如下图,方块内的值(i,j)表示第i行第j列。(1,1)位置如果放了皇后,那么(1,1)位置所在的行,列,斜线上都不能再放皇后。 如何判断两个位置冲突呢? (1)判断两个位置是否再斜线上:根据斜率 A(1,1)位置,B(2,0)位置和C(2,2)位置,A和B冲突:(0-1)/(2-1)==-1,A和C冲突:(2-1)/(2-1)==1。 因此,对于任意两点A(x1,y1)和B(x2,y2),两点斜线冲突满足条件:abs((y2-y1)/(x2-x1))==1, 该公式转换为: abs(y2-y1)== abs(x2-x1) (2)判断两个位置是否在同一列/同一行 任意两点A(x1,y1)和B(x2,y2)在同一列满足条件: y1 == y2 ,在同一行满足条件: x1 == x2 判断冲突代码如下: int valid(int row, int col) //判断第row行第col列是否可以放置皇后 { int i; for (i = 0; i < QUEEN;

使用java语言实现八皇后问题

老子叫甜甜 提交于 2019-12-14 13:39:31
八皇后问题,在一个8X8的棋盘中,放置八个棋子,每个棋子的上下左右,左上左下,右上右下方向上不得有其他棋子。正确答案为92中,接下来用java语言实现。 解: package eightQuen; /** * 八皇后问题 * * @author 83771 * */ public class eight { // 定义一个数组 表示棋盘 public static Integer[][] checkerBoard = new Integer[8][8]; // 棋盘副本 public static Integer[][] checkerBoardCopy = new Integer[8][8]; // 计数器 用于计数有多少种方法 public static Integer jishu = 1; // 定义横竖斜方向上是否有棋子 public static boolean flag1 = true; public static boolean flag2 = true; public static boolean flag3 = true; public static boolean flag4 = true; // 初始化一个棋盘 8x8 public static void init() { for (int i = 0; i < 8; i++) { for (int j =

暴力回溯法 解八皇后

 ̄綄美尐妖づ 提交于 2019-12-11 03:45:41
国际象棋 八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 public class _8Queen { //回溯法,暴力解8皇后 private static int ways = 0; //返回解法个数 public static int f8queen() { int[][] board = new int[8][8]; ways = 0; p_f8queen(board, 0); return ways; } private static void p_f8queen(int[][] board, int row) { if (row > 7) { ways++; printBoard(board); //最后一行穷举完,输出棋盘 return; } for (int col = 0; col < 8; col++) { if (check(board, row, col)) { //检测是否符合规则 board[row][col] = 1; //放皇后棋子 p_f8queen(board, row + 1);//进入下一行 board[row][col] = 0; //清除 } } }