递归算法实现“八皇后问题”

合集下载

组合数学中的棋盘问题

组合数学中的棋盘问题

组合数学中的棋盘问题棋盘问题是组合数学中一个经典而又有趣的问题,它涉及到在一个n × n 的棋盘上放置一定数量的棋子并满足特定的条件。

在本文中,我们将探讨棋盘问题的一些常见形式以及解决方法。

一、八皇后问题八皇后问题是指在一个 8 × 8 的棋盘上放置 8 个皇后,并且每个皇后都不能相互攻击,即任意两个皇后不得处于同一行、同一列或同一对角线上。

这个问题可以通过回溯法来解决。

我们可以逐行放置皇后,并在每一行中使用循环判断每个格子是否满足条件。

如果满足条件,则继续递归下一行;如果不满足条件,则回溯到上一行继续判断。

当所有皇后都放置完毕时,即找到了一种解法。

二、骑士周游问题骑士周游问题是指在一个 n × n 的棋盘上,骑士按照国际象棋中骑士的移动规则进行移动,需要从起始格子出发,经过棋盘的每个格子,最终回到起始格子,且每个格子只能经过一次。

这个问题可以通过深度优先搜索或者广度优先搜索来解决。

我们可以从起始格子开始,按照骑士的移动规则依次遍历所有相邻的格子,并标记已访问的格子。

当所有格子都被访问过,并且最后的格子可以与起始格子连通,则找到了一种解法。

三、数独问题数独问题是指在一个 9 × 9 的棋盘上填入数字,使得每一行、每一列和每一个 3 × 3 的小方格中的数字都是 1 到 9 的不重复数字。

这个问题可以通过回溯法来解决。

我们可以逐格填入数字,并在每个格子中使用循环判断每个数字是否满足条件。

如果满足条件,则继续递归下一个格子;如果不满足条件,则尝试下一个数字。

当所有格子都填满时,即找到了一种解法。

四、六角形拼图问题六角形拼图问题是指在一个六角形的棋盘上,使用特定形状的六角形块填满整个棋盘。

这个问题可以通过搜索算法来解决。

我们可以从一个起始位置开始,依次尝试放置不同形状的六角形块。

每次放置块后,判断是否满足放置要求。

如果满足要求,则继续递归下一个位置;如果不满足要求,则尝试下一个形状的块。

java递归求八皇后问题解法

java递归求八皇后问题解法

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

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

⾼斯认为有76种⽅案。

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

⽹上有很多⼋皇后的⼩游戏,不清楚规则的可以体验⼀把。

递归理解由于我们使⽤经典的递归回溯算法,所以要先理解递归的调⽤过程,在使⽤递归前我们先看下普通⽅法的调⽤过程在JVM中如何体现。

⾸先我们来看下jvm中五个重要的空间,如下图所⽰这⾥我们主要关注栈区,当调⽤某个⽅法时会在栈区为每个线程分配独⽴的栈空间,⽽每个⽅法都会以栈帧的形式压⼊栈中,即每个⽅法从进⼊到退出都对应着⼀个栈帧的压栈和出栈。

如下图所⽰在每个栈帧中都会有⽅法独⽴的局部变量表,操作数栈,动态连接,返回地址等信息。

如下图所⽰理解了jvm程序栈的结构后,下⾯我们以图解的⽅式先讲解⼀下普通⽅法(理解普通⽅法调⽤过程后,再讲解递归的调⽤过程)的调⽤过程。

假设程序main⽅法⾸先调⽤了method1,在method1中调⽤了method2,在method2中调⽤method3。

代码如下1public static void main(String []args){2 method1();3 }5private static void method1(){6 System.out.println("method1调⽤开始");7 method2();8 System.out.println("method1调⽤结束");9 }1011private static void method2(){12 System.out.println("method2调⽤开始");13 method3();14 System.out.println("method2调⽤结束");15 }16private static void method3(){17 System.out.println("method3调⽤开始");18 System.out.println("method3调⽤结束");19 } 当执⾏main⽅法时,会执⾏以下步骤 1)⾸先将main⽅法压⼊栈中,在main⽅法中调⽤method1,⽅法mehod1会压⼊栈中,并执⾏打印“method1调⽤开始” 2)执⾏到第7⾏时,将method2压⼊栈中,执⾏method2⽅法的代码打印出“method2调⽤开始” 3)执⾏到第13⾏时调⽤method3⽅法,将method3⽅法压⼊栈中,执⾏method3⽅法打印“method3调⽤开始”,⽅法压⼊栈中的过程图解,如下图所⽰ 当执⾏到图4中的method3⽅法打印出“method3调⽤开始”后会执⾏以下步骤 1)method3执⾏打印“method3调⽤结束”后method3⽅法体已全部执⾏完毕,method3⽅法会出栈,并根据栈帧中程序计数器记录的调⽤者调⽤本⽅法的所在⾏返回。

算法——八皇后问题(eightqueenpuzzle)之回溯法求解

算法——八皇后问题(eightqueenpuzzle)之回溯法求解

算法——⼋皇后问题(eightqueenpuzzle)之回溯法求解⼋皇后谜题是经典的⼀个问题,其解法⼀共有92种!其定义:1. ⾸先定义⼀个8*8的棋盘2. 我们有⼋个皇后在⼿⾥,⽬的是把⼋个都放在棋盘中3. 位于皇后的⽔平和垂直⽅向的棋格不能有其他皇后4. 位于皇后的斜对⾓线上的棋格不能有其他皇后5. 解出能将⼋个皇后都放在棋盘中的摆法这个问题通常使⽤两种⽅法来求解:1. 穷举法2. 回溯法(递归)本⽂章通过回溯法来求解,回溯法对⽐穷举法⾼效许多,让我们学习如何实现吧!实现思想:1. 我们先在棋盘的第0⾏第1个棋格放下第⼀个皇后2. 下⼀⾏寻找⼀个不冲突的棋格放下下⼀个皇后3. 循环第2步4. 如果到某⼀⾏全部8个格⼦都⽆法放下皇后,回溯到前⼀⾏,继续寻找下⼀个不冲突的棋格5. 把8个皇后都放在棋盘之后,输出或存储摆法,结束实现(Java)算法:定义棋盘我们通过⼀个⼆维整型数组表⽰⼀个棋盘数组内为1是放下了的皇后,0则是空⽩的棋格我们下下⾯定义⼀个⽅法:通过检查棋格是否为1来知道是不是有皇后1// 定义⼀个棋盘2static int chessboard[][] = new int[8][8];检查冲突这个⽅法⽤来检查冲突:在⽔平垂直⽅向、斜⾓上的棋格有⽆其他皇后,传⼊的(x,y)是需要检查的棋格,如检查棋格(1,0)即棋盘的第2⾏第1个,是否能放下皇后。

1// 检查是否符合规则2private static boolean checked(int x,int y){3for(int i = 0;i<y;i++){4// 检查⽔平垂直⽅向5if(chessboard[x][i]==1)return false;6// 检测左斜⾓7if((x-y+i>=0)&&chessboard[x-y+i][i]==1)return false;8// 检查右斜⾓9if((x+y-i<=7)&&chessboard[x+y-i][i]==1)return false;10 }11return true;12 }放下皇后我们在每⼀⾏都执⾏以下步骤,通过从第1个棋格到第8个遍历寻找可以放下皇后的棋格如果放下了皇后,我们就可以继续放下下⼀个了,将⾏数+1,我们递归调⽤这个⽅法1public static boolean solve(int y){2// 将⼀⾏的8种情况都扫描⼀次3for(int i = 0;i<8;i++){4// 每次检测前都将当前⾏清空,避免脏数据5for(int k = 0;k<8;k++)chessboard[k][y]=0;6if(checked(i, y)){7 chessboard[i][y] = 1;8// 当前⼀⾏已经获得解法,进⼊下⼀⾏9 solve(y+1);10 }11 }12return false;13 }算法边界当我们放下了所有8个皇后后,需要⼀个终⽌条件,我们在⾏数y=8时,结束算法同时你可以输出⼀个棋盘摆法了!恭喜你已经把这个经典问题解决了!1// 当y=8时,已经找到⼀种解决⽅法2if(y == 8){3return true;4 }以下是完整的算法1public class EightQueen{2// 定义⼀个棋盘3static int chessboard[][] = new int[8][8];4// 计数器5static int count = 0;67// 解题⽅法8public static boolean solve(int y){9// 当y=8时,已经找到⼀种解决⽅法,计数器加⼀并输⼊摆法10if(y == 8){11 System.out.println("solved!");12 show();13 count++;14return true;15 }16// 将⼀⾏的8种情况都扫描⼀次17for(int i = 0;i<8;i++){18// 每次检测前都将当前⾏清空,避免脏数据19for(int k = 0;k<8;k++)chessboard[k][y]=0;20if(checked(i, y)){21 chessboard[i][y] = 1;22// 当前⼀⾏已经获得解法,进⼊下⼀⾏23 solve(y+1);24 }25 }26return false;27 }28// 检查是否符合规则29private static boolean checked(int x,int y){30for(int i = 0;i<y;i++){31// 检查垂直⽅向32if(chessboard[x][i]==1)return false;33// 检测左斜⾓34if((x-y+i>=0)&&chessboard[x-y+i][i]==1)return false;35// 检查右斜⾓36if((x+y-i<=7)&&chessboard[x+y-i][i]==1)return false;37 }38return true;39 }40// 输出棋盘摆法41public static void show(){42for(int i = 0;i<8;i++){43for(int j = 0;j<8;j++){44 System.out.print(chessboard[j][i]+" ");45 }46 System.out.println("");47 }48 }49 }在执⾏这个算法后:have 92 ways to sovle it!我们获得了92种棋盘摆法!。

八皇后问题详细的解法

八皇后问题详细的解法

若无法放下皇后则回到上一行, 即回溯
当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列开 始搜索,枚举出所有的“解状态”:
从中找出满足约束条件的“答案状态”。

八皇后实验报告

八皇后实验报告

八皇后实验报告八皇后实验报告引言:八皇后问题是一个经典的数学问题,它要求在一个8x8的国际象棋棋盘上放置8个皇后,使得任意两个皇后都不会互相攻击。

这个问题看似简单,但实际上却充满了挑战。

在本次实验中,我们将探索八皇后问题的解法,并通过编写算法来解决这个问题。

一、问题背景:八皇后问题最早由数学家马克斯·贝瑟尔于1848年提出,它是一道经典的递归问题。

在国际象棋中,皇后可以在同一行、同一列或同一对角线上进行攻击,因此我们需要找到一种方法,使得8个皇后彼此之间不会相互攻击。

二、解决方法:为了解决八皇后问题,我们可以使用回溯法。

回溯法是一种穷举搜索的方法,它通过逐步尝试所有可能的解决方案,直到找到符合要求的解。

具体步骤如下:1. 初始化一个8x8的棋盘,并将所有格子标记为无皇后。

2. 从第一行开始,依次尝试在每一列放置一个皇后。

3. 在每一列中,检查当前位置是否符合要求,即与已放置的皇后不在同一行、同一列或同一对角线上。

4. 如果当前位置符合要求,将皇后放置在该位置,并进入下一行。

5. 如果当前位置不符合要求,尝试在下一列放置皇后。

6. 重复步骤3-5,直到找到一个解或者所有可能的位置都已尝试过。

7. 如果找到一个解,将其输出;否则,回溯到上一行,继续尝试下一列的位置。

三、编写算法:基于上述步骤,我们可以编写一个递归函数来解决八皇后问题。

伪代码如下所示:```function solveQueens(board, row):if row == 8:print(board) # 打印解returnfor col in range(8):if isSafe(board, row, col):board[row][col] = 1solveQueens(board, row + 1)board[row][col] = 0function isSafe(board, row, col):for i in range(row):if board[i][col] == 1:return Falseif col - (row - i) >= 0 and board[i][col - (row - i)] == 1:return Falseif col + (row - i) < 8 and board[i][col + (row - i)] == 1:return Falsereturn Trueboard = [[0]*8 for _ in range(8)]solveQueens(board, 0)```四、实验结果:通过运行上述算法,我们得到了八皇后问题的所有解。

算法设计与分析实验报告—八皇后问题

算法设计与分析实验报告—八皇后问题

算法设计与分析实验报告—八皇后问题-姓名:***学号:********班级:软件83【问题描述】在国际象棋盘上放八个皇后,要求任一皇后吃不到别人,也不受其他皇后的攻击,求出问题的所有解。

【问题分析&算法设计】用8元组x[1: n]表示8后问题。

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

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

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

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

这两个方程分别等价于i – k = j – l和i – k = l – j。

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

问题的隐约束化成了显约束。

用回溯法解决8皇后问题时,用完全8叉树表示解空间。

【算法实现】#include "stdio.h"#include "math.h"#include "iostream.h"#define N 8 /* 定义棋盘大小*/static int sum; /* 当前已找到解的个数*/static int x[N]; /* 记录皇后的位置,x[i]表示皇后i放在棋盘的第i行的第x[i]列*//* 每找到一个解,打印当前棋盘状态*/void Show(){sum++;cout << "第" << sum << "种情况:" << endl;cout << "坐标为:\t";for(int k = 0; k < N; k++)cout << '(' << k+1 << ',' << x[k] << ") ";cout << endl;cout << "---------------------------------\n";for (int i = 0; i < N; i ++){for (int j = 0; j < N; j ++)if (j == x[i]) //printf("@ ");cout << "* | ";else //printf("* ");cout << " | ";cout << "\n---------------------------------\n";}}/* 确定某一位置皇后放置与否,放置则返回1,反之返回0 */int Judge(int k){// 测试皇后k在第k行第x[k]列时是否与前面已放置好的皇后相攻击。

数据结构与算法中的“递归”——用回溯法求解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个皇后的位置比较。

八皇后的递归和非递归的解法(C++)

八皇后的递归和非递归的解法(C++)

八皇后的递归和非递归的解法(C++)八皇后的递归和非递归的解法(C++)//描述:用递归和非递归模拟n皇后问题//输入:问题的规模:n//输出:皇后放置的方法排列和总数#include<iostream>#include<iomanip>#include<cmath>#include<stack>using namespace std;//利用递归求解皇后问题 x[i]表示皇后放在第i行第x[i]列static int count;//判断如果皇后放在第i行,第j列是否与前面的皇后冲突bool place(int i,int j,int* path)//path存放路径{int row;for(row=0;row<i;row++){if(abs(row-i)==abs(path[row]-j))//在同一条斜线上return false;if(j==path[row])//在同一列return false;}return true;}//利用递归来求解,而且当row==0时,即求解全局的解//path[n]用来存放路径void queen(int row,int* path,int n)if(row==n){//输出结果,并将办法数加1for(int i=0;i<n;i++){cout<<setw(5)<<left<<path[i];}cout<<endl;count++;}else{int j;//表示当前列是否可行for(j=0;j<n;j++){//如果可行,则放置并且递归调用处理下一行if(place(row,j,path)){path[row]=j;//这里相当于入栈的过程queen(row+1,path,n);}}}}//利用迭代来求解void queen_another(int n,int* path) {int i=0;for(i=0;i<n;i++){int j=0;for(;j<n;j++){if(place(i,j,path)){path[i]=j;cout<<"row "<<i<<"col "<<j<<endl; break;}}//没有合适的位置,所以要回溯到上一个最合适的节点if(j==n){i--;while(i>=0){int k=path[i]+1;while(k<n&&!(place(i,k,path)))k++;if(k==n)i--;else{path[i]=k;break;}if(i<0){cout<<"there is no way "<<endl;return;}}}if(i==n)for(int j=0;j<n;j++){cout<<setw(5)<<left<<path[j];path[j]=-1000;}}//利用栈来模拟递归,在某个扩展节点出处,将所有符合条件的节点加入到里面struct pos{int row;int col;};//找到当前最合适的节点,如果没有找到则返回-1int find_col(int row,int col,int* path,int n){int j;for(j=col;j<n;j++){if(place(row,j,path))return j;if(j==n)return -1;}//利用栈来模拟八皇后问题void stack_stimu(int n,int* path){stack<struct pos> s;int currow=0;int flag=0;//主要结构分为两部分,第一按照正常顺序寻找节点//然后找出回溯的情况:在八皇后问题中主要有两中:1.到达结尾找出路径 2.当前行没有满足条件的位置while(true){if(currow<n){int col=find_col(currow,0,path,n);if(col!=-1){pos node;node.row=currow;node.col=col;s.push(node);path[currow]=col;currow++;}elseflag=1;}else{for(int i=0;i<n;i++)cout<<setw(5)<<left<<path[i];cout<<endl;count++;flag=1;}// 进行回溯if(flag==1){//描述了回溯的过程while(!s.empty()){pos temp=s.top();if(temp.col!=7){//查找当前最适合的节点,并入栈int j=find_col(temp.row,temp.col+1,path,n); if(j!=-1){pos node;node.row=temp.row;node.col=j;s.pop();s.push(node);path[temp.row]=j;currow=temp.row+1;flag=0;break;}elses.pop();}elses.pop();}if(s.empty())return;//函数的出口处}}//end for while(true)}int main(){cout<<"Queen Place Problem:"<<endl; cout<<"Input the value of n"<<endl; int n;cout<<" n>";cin>>n;int* path=new int[n];//初始化for(int i=0;i<n;i++)path[i]=-1000;//queen_another(n,path);//queen(0,path,n);stack_stimu(n,path);cout<<"the count is: "<<count<<endl; getchar();getchar(); return 0; }。

八皇后问题递归算法

八皇后问题递归算法

八皇后问题递归算法八皇后问题是一个经典的数学问题,其目标是在一个8×8的棋盘上放置8个皇后,使得没有两个皇后位于同一行、同一列或同一斜线上。

这个问题可以通过递归算法来求解,本文将详细介绍八皇后问题的递归算法及其实现过程。

我们需要定义一个函数来判断当前位置是否可以放置皇后。

该函数的输入参数为当前行和当前列,输出为一个布尔值,表示该位置是否可以放置皇后。

具体实现如下:```bool isSafe(int board[8][8], int row, int col){int i, j;// 检查当前列是否有其他皇后for (i = 0; i < row; i++)if (board[i][col])return false;// 检查左上方是否有其他皇后for (i = row, j = col; i >= 0 && j >= 0; i--, j--)if (board[i][j])return false;// 检查右上方是否有其他皇后for (i = row, j = col; i >= 0 && j < 8; i--, j++)if (board[i][j])return false;return true;}```接下来,我们可以使用递归算法来解决八皇后问题。

递归算法的思想是将问题分解为子问题,然后逐步解决子问题,最终得到原问题的解。

具体的递归算法如下:```bool solveNQueens(int board[8][8], int row){// 所有行都已经放置好了皇后,得到了一个解if (row == 8)return true;// 尝试在当前行的每个列中放置皇后for (int col = 0; col < 8; col++)// 检查当前位置是否可以放置皇后if (isSafe(board, row, col)){// 放置皇后board[row][col] = 1;// 递归求解下一行if (solveNQueens(board, row + 1))return true;// 回溯,撤销当前位置的皇后board[row][col] = 0;}}// 无法找到解return false;}```我们可以编写一个主函数来调用递归算法并打印结果。

八皇后问题实验报告

八皇后问题实验报告

实验报告——八皇后问题求解(递归和非递归)学号:专业年级:姓名:一、需求分析(要实现的功能描述)1.问题描述八皇后问题是一个以国际象棋为背景的问题:如何能够在8×8的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。

八皇后问题可以推广为更一般的n皇后摆放问题:这时棋盘的大小变为n×n,而皇后个数也变成n。

当且仅当n=1或n≥4时问题有解。

八皇后问题最早是由国际国际象棋棋手马克斯·贝瑟尔于1848年提出。

诺克也是首先将问题推广到更一般的n皇后摆放问题的人之一。

2.实现功能八皇后问题实现了在棋盘上摆放八个皇后的功能,这八个皇后任意两个皇后都不能处于同一条横行、纵行或斜线上。

3.测试数据测试数据可以通过手工寻找三组满足需要的值,测试数组(M,N),其中M代表皇后所在的行,N代表皇后所在的列。

例如,第一组测试数据:(1,4)、(2,7)、(3,3)、(4、8)、(5,2)、(6,5)、(7,1)、(8,6);第二组测试数据(1,4)、(2,2)、(3,7)、(4,3)、(5,6)、(6,8)、(7,5)、(8,1)。

最后与编程求得的结果进行比较。

如果这三组数据在最后编程求得的结果中,说明程序的编写基本没有什么问题。

二、概要设计在进行概要设计的过程中,要清楚整个程序包含的功能模块及模块间的调用关系。

对于八皇后问题,整个程序中应该包括主函数模块,摆放皇后的函数模块,以及判断皇后的位置是否摆放正确的判断模块。

对于模块间的关系,在运行主函数的过程中会调用摆放皇后的函数模块,在摆放皇后的函数模块中,又会调用判断皇后位置是否摆放正确的判断模块。

三、详细设计抽象数据类型中定义的各种操作算法实现(用N-S图描述)对于求解八皇后问题的非递归算法,N-S图如下:对于八皇后问题求解的递归算法,N-S图如下:四、调试分析1.程序在调式过程中出现的问题及解决方法由于对于C语言编程问题掌握的并非十分熟练,因而在程序的调试过程中出现了一些问题。

八皇后问题的最佳解决方案

八皇后问题的最佳解决方案

② 算法描述
3.2 递归回溯法解决八皇后问题
int a[20],b[20],c[40],d[40]; int n,t,i,j,k; //t记录解的个数,i掌握行,j掌握列
main( )
{ int i, input(n); //输入皇后的个数
for(i=1;i<=n;i++) { b[i]=0;//记录棋盘n个列 c[i+1]=0; c[n+i]=0;//记录棋盘负对角线 d[i]=0; d[n+i-1]=0;//记录棋盘主对角线
2 算法设计与分析
报告3 算法设计与分析试验报告
八皇后问题的最正确解决方 案
内容提要
1 回溯法概述 2 八皇后问题 3 解决八皇后问题常用算法 4 算法分析与总结
1 回溯法概述
一 回溯法
回溯法实际是一个类似枚举的搜寻尝试方 法,它的主题思想是在搜寻尝试中找问题的 解,当不满足求解条件就”回溯”(返回),尝 试别的路径。回溯算法是尝试搜寻算法中最 为根本的一种算法,其承受了一种“走不通就 掉头”的思想,作为其掌握构造。本文主要 描述递归回溯与非递归回溯,并用这两个算 法解决经典的“八皇后”问题,找出该问题的 最正确解决方案。
3.2 非递归回溯法解决八皇后问题
t a[20],n;
Main2
{ input(n); bckdate〔n〕;} //初始化,输入皇后数目
backdate (int n) //该函数是用来查找满足约束的全部解
{ int k;
a[1]=0; k=1; //k用来表示第k个皇后
while( k>0 ) {a[k]=a[k]+1; while ((a[k]<=n) and (check(k)=0)) //搜

八皇后问题实验报告递归非递归javaC语言+分析2

八皇后问题实验报告递归非递归javaC语言+分析2

数据结构课程设计题目:八皇后问题指导教师:胡*学生院系:数学学院学生班级:信计*班学生姓名:黎*文学生学号: **********2016年12月30日目录一.功能以及需求分析 (3)1.1 问题的由来和背景 (3)1.2 问题的基本解决思路 (3)1.3 问题的应用 (3)二.总体设计 (4)2.1 运行环境 (4)2.2 程序框架 (4)2.3 算法分析 (4)2.3.1 总体算法分析 (4)2.3.2 非递归算法分析 (6)2.3.3 递归算法的分析 (6)三.详细设计 (6)3.1 递归法的详细设计 (6)3.2 非递归法的详细设计 (8)四.具体实现及运行 (10)4.1 QueenMainl类的实现: (10)4.2 QueenNR类: (10)4.3 QueenRS类: (11)4.4 C语言程序: (11)五. 总结 (12)六.代码清单 (13)6.1 Java代码: (13)6.2 C语言源代码: (20)一.功能以及需求分析1.1 问题的由来和背景八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。

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

高斯认为有76种方案。

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

计算机发明后,有多种计算机语言可以解决此问题。

八皇后问题是一个以国际象棋为背景的问题:如何能够在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。

八皇后问题可以推广为更一般的n皇后摆放问题:这时棋盘的大小变为n×n,而皇后个数也变成n。

当且仅当 n = 1 或 n ≥ 4 时问题有解。

回溯算法在八皇后问题中的应用

回溯算法在八皇后问题中的应用

回溯算法在八皇后问题中的应用八皇后问题是一个经典的回溯算法应用示例。

这个问题的要求是在一个8×8的棋盘上放置8个皇后,使得任意两个皇后都不在同一行、同一列以及同一斜线上。

回溯算法通过穷举所有可能的解,并逐步排除不满足条件的情况,最终找到问题的解。

下面我们来详细介绍回溯算法在八皇后问题中的应用。

一、问题描述八皇后问题的规则是在一个8×8的棋盘上放置8个皇后,要求任意两个皇后都不能互相攻击。

皇后可以横向、纵向或者对角线方向进行攻击。

找到所有满足条件的放置方式即为问题的解。

对于八皇后问题,一共有92种不同的解。

二、回溯算法的原理回溯算法是一种通过穷举所有可能解来寻找问题解的方法。

对于八皇后问题,回溯算法从棋盘的第一行开始,尝试在每一个位置上放置皇后。

如果该位置上放置皇后不违反规则,那么就继续到下一行继续放置皇后。

如果在某一行无法找到满足条件的位置,那么就回溯到上一行重新选择位置放置皇后。

通过不断的回溯和回退,最终找到问题的解。

三、回溯算法的步骤下面我们来介绍一下回溯算法在八皇后问题中的具体步骤:1. 初始化棋盘:创建一个8×8的棋盘,并将所有位置初始化为0,表示暂未放置皇后。

2. 递归方法:创建一个递归方法来实现回溯算法。

该方法中有一个参数表示当前所在的行数。

3. 判断边界条件:如果当前行数等于8,说明已经找到了一个满足条件的解,将解保存下来,并结束递归。

4. 在当前行中遍历所有位置:对于当前行,循环遍历所有的列,尝试在每个位置上放置皇后。

5. 判断是否满足条件:对于每个位置,判断该位置与已经放置的皇后是否冲突。

如果冲突,则尝试下一个位置;如果不冲突,则继续到下一行递归放置皇后。

6. 回溯操作:如果所有位置都尝试完毕,都无法找到满足条件的位置,那么就回溯到上一行重新选择位置放置皇后。

7. 输出结果:最终输出所有满足条件的解。

四、代码实现以下是使用Python语言实现八皇后问题的回溯算法示例代码:```def solve_n_queens():queens = [-1] * 8 # 存储每一行皇后所在的列数result = [] # 存储所有满足条件的解 def is_valid(row, col):for i in range(row):if queens[i] == col or \queens[i] == col - row + i or \ queens[i] == col + row - i:return Falsereturn Truedef dfs(row):if row == 8:result.append(queens[:])returnfor col in range(8):if is_valid(row, col):queens[row] = coldfs(row + 1)dfs(0)return resultqueens = solve_n_queens()for queen in queens:print(queen)```五、总结回溯算法是一种穷举搜索的方法,通过不断尝试和回退来寻找问题的解。

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; }}}}}。

八皇后回溯算法的实现

八皇后回溯算法的实现

回溯算法的实现(1)为解决这个问题,我们把棋盘的横坐标定为i,纵坐标定为j,i和j的取值范围是从1到8。

当某个皇后占了位置(i,j)时,在这个位置的垂直方向、水平方向和斜线方向都不能再放其它皇后了。

用语句实现,可定义如下三个整型数组:a[8],b[15],c[24]。

其中:a[j-1]=1 第j列上无皇后a[j-1]=0 第j列上有皇后b[i+j-2]=1 (i,j)的对角线(左上至右下)无皇后b[i+j-2]=0 (i,j)的对角线(左上至右下)有皇后c[i-j+7]=1 (i,j)的对角线(右上至左下)无皇后c[i-j+7]=0 (i,j)的对角线(右上至左下)有皇后(2)为第i个皇后选择位置的算法如下:for(j=1;j<=8;j++) /*第i个皇后在第j行*/if ((i,j)位置为空))/*即相应的三个数组的对应元素值为1*/{占用位置(i,j)/*置相应的三个数组对应的元素值为0*/if i<8为i+1个皇后选择合适的位置;else 输出一个解}#include <graphics.h>#include <stdlib.h>#include <stdio.h>#include <dos.h>char n[3]={'0','0'};/*用于记录第几组解*/int a[8],b[15],c[24],i;int h[8]={127,177,227,277,327,377,427,477};/*每个皇后的行坐标*/int l[8]={252,217,182,147,112,77,42,7};/*每个皇后的列坐标*/void *arrow;void try(int i){int j;for (j=1;j<=8;j++)if (a[j-1]+b[i+j-2]+c[i-j+7]==3) /*如果第i列第j行为空*/{a[j-1]=0;b[i+j-2]=0;c[i-j+7]=0;/*占用第i列第j行*/putimage(h[i-1],l[j-1],arrow,COPY_PUT);/*显示皇后图形*/delay(500);/*延时*/if(i<8) try(i+1);else /*输出一组解*/{n[1]++;if (n[1]>'9') {n[0]++;n[1]='0';}bar(260,300,390,340);/*显示第n组解*/outtextxy(275,300,n);delay(3000);}a[j-1]=1;b[i+j-2]=1;c[i-j+7]=1;putimage(h[i-1],l[j-1],arrow,XOR_PUT);/*消去皇后,继续寻找下一组解*/ delay(500);}}int main(void){int gdrive=DETECT,gmode,errorcode;unsigned int size;inITgraph(&gdrive,&gmode,"");errorcode=graphresult();if (errorcode!=grOk){printf("Graphics error\n");exIT(1);}rectangle(50,5,100,40);rectangle(60,25,90,33);/*画皇冠*/line(60,28,90,28);line(60,25,55,15);line(55,15,68,25);line(68,25,68,10);line(68,10,75,25);line(75,25,82,10);line(82,10,82,25);line(82,25,95,15);line(95,15,90,25);size=imagesize(52,7,98,38); arrow=malloc(size);getimage(52,7,98,38,arrow);/*把皇冠保存到缓冲区*/clearviewport();settextstyle(TRIPLEX_FONT, HORIZ_DIR, 4);setusercharsize(3, 1, 1, 1);setfillstyle(1,4);for (i=0;i<=7;i++) a[i]=1;for (i=0;i<=14;i++) b[i]=1;for (i=0;i<=23;i++) c[i]=1;for (i=0;i<=8;i++) line(125,i*35+5,525,i*35+5);/*画棋盘*/for (i=0;i<=8;i++) line(125+i*50,5,125+i*50,285);try(1);/*调用递归函数*/delay(3000);closegraph();free(arrow);}。

八皇后问题(递归+非递归)

八皇后问题(递归+非递归)

八皇后问题(递归+非递归)Xredman posted @ 2009年6月04日 21:15 in 以前博文 , 442 阅读一.问题描述在8×8格的国际象棋棋盘上放置八个皇后,使得任意两个皇后不能互相攻击,即任何行、列或对角线(与水平轴夹角为45°或135°的斜线)上不得有两个或两个以上的皇后。

这样的一个格局称为问题的一个解。

请用递归与非递归两种方法写出求出八皇后问题的算法。

二.解题思路描述一个正确的解应当是每一列,每一行,每一条斜线上均只有一个皇后。

对于递归算法,本人才有模拟的方式进行,而且,我觉得开辟一个二维数组更显而易见。

首先,从空棋盘开始摆放,保证第m行m个皇后互不攻击,然后摆放第m+1个皇后。

当然对于第m+1个皇后可能有多种摆放方法,由此,我必须一一枚举,采用回溯策略是可行且合乎逻辑的。

而对于非递归算法,我只是借助于书本上一个递归改为非递归的框架,依次搭建而已。

在此过程中,我采用一维数组,一位对于八皇后问题,每一行不可能存在二个及二个以上的皇后,board[i]表示第i行棋盘摆放的位置为第board[i]列。

递归方法借助于系统提供的栈,而我非递归算法的实现,仅仅是自己构造一个栈而已。

递归解法#include <iostream>#include <cstdio>#include <sys/timeb.h>using namespace std;const int MAX_SIZE = 100;enum flag {blank ='X',queen = 1};char Chess[MAX_SIZE][MAX_SIZE];//棋盘图int n;//解决n皇后问题int total;//用于计摆放方式void Init(){//对棋牌进行初始化for(int i = 0; i < n; i++)for(int j = 0; j < n; j++)Chess[i][j] = blank;total = 0;//初始时有零中摆放方式}bool Judge(int r,int c){//判断(r,c)位置是否可放置int i,j;for(i = r + 1; i < n; i++)if(Chess[i][c] == queen)return false;//说明c列上已有一皇后for(i = c + 1; i < n; i++)if(Chess[r][i] == queen)return false;//说明r行上已有一皇后for(i = r + 1, j = c + 1; (i < n) && (j < n); i++, j++)if(Chess[i][j] == queen)return false;//45度斜线上已有一皇后for(i = r + 1, j = c - 1; (i <n) && (j >= 0); i++, j--)if(Chess[i][j] == queen)return false;//135度斜线上已有一皇后return true;//排除四种情况后,说明(r,c)点可放置皇后}void Backtrack(int k,int cnt){//回溯算法主程序if(k < 0 || cnt == n)//棋牌摆放完毕 or 以摆满n后{if(cnt == n){printf("No.%d:\n",++total);for(int i = 0; i < n; i++){for(int j = 0; j < n; j++)printf(" %c ",Chess[i][j]);putchar('\n');}putchar('\n');}}else{int r = k / n, c = k % n;if(Judge(r,c)){//可放置一皇后Chess[r][c] = queen;Backtrack(k-1,cnt+1);Chess[r][c] = blank;}Backtrack(k-1,cnt);}}int main(){//此为主函数timeb t1,t2;long kk;cout<<"输入皇后个数:";while(cin>>n){Init();ftime(&t1);Backtrack(n*n-1,0);ftime(&t2);cout<<"计算"<<n<<"后问题总共可有"<<total<<"种摆法!"<<endl;kk = (t2.time-t1.time)*1000 +litm;cout<<"本次回溯耗时:"<<kk<<"毫秒"<<endl;system("PAUSE");cout<<"输入皇后个数:";}return0;}非递归解法#include <iostream>#include <sys/timeb.h>#define N 100using namespace std;int board[N];int n,sum;void init(){for(int i = 1; i <= n; i++)board[i] = 0;}void display(){int i,j;cout<<"No."<<sum<<endl;for(i = 1; i <= n; i++){for(j = 1; j <= n; j++)if(board[i] == j)cout<<"Q ";elsecout<<"X ";cout<<endl;}cout<<endl;}bool canPut(int k){for(int i = 1; i < k; i++)if((abs(k - i) == abs(board[k] - board[i])) || board[i] == board[k])return false;//1.是否在同一斜线;2.是否位于同一列return true;}void Backtrack(){board[1] = 0;int k = 1;while(k > 0){board[k]++;while((board[k] <= n) && !(canPut(k)))board[k] += 1;if(board[k] <= n)if(k == n){sum++;display();}else{k++;board[k] = 0;}elsek--;}}int main(){timeb t1,t2;long kk;cout<<"输入皇后个数:";while(cin>>n){init();sum = 0;ftime(&t1);Backtrack();ftime(&t2);cout<<"总共排列方式为:"<<sum<<endl;kk = (t2.time-t1.time)*1000 + litm; cout<<"本次回溯耗时:"<<kk<<"毫秒"<<endl;system("PAUSE");cout<<"输入皇后个数:";}return0;}。

c++八皇后问题最简单算法

c++八皇后问题最简单算法

八皇后问题是一个经典的回溯算法问题。

下面是一个使用C语言实现的简单算法:c复制代码#include<stdio.h>#include<stdbool.h>#define N 8int col[N] = {0}; // 表示皇后所在的列int queens[N][N] = {0}; // 存储棋盘状态bool is_valid(int row, int col) {for (int i = 0; i < row; i++) {if (queens[i][col] || queens[i][col - (row - i)] || queens[i][col + (row -i)]) {return false;}}return true;}void backtrack(int row) {if (row == N) { // 找到了一组解for (int i = 0; i < N; i++) {for (int j = 0; j < N; j++) {printf("%d ", queens[i][j]);}printf("\n");}return;}for (int col = 0; col < N; col++) {if (is_valid(row, col)) { // 如果当前位置是合法的,则放置皇后queens[row][col] = 1;col[row] = col; // 记录每行皇后所在的列backtrack(row + 1); // 继续放下一行的皇后queens[row][col] = 0; // 回溯,撤销当前位置的皇后}}}int main() {backtrack(0); // 从第0行开始放皇后return0;}在上面的代码中,我们使用一个一维数组col来记录每一行皇后所在的列。

在is_valid函数中,我们检查当前位置是否合法,即与前面的皇后不冲突。

从八皇后问题引发递归回溯算法的思考

从八皇后问题引发递归回溯算法的思考
是递归的出之一袁 一般是下标越界袁 条件不满足 等情况遥 2.2 成功是问题有解
找到答案袁 是递归理想的出口袁 一般是到达目的 地袁 计数袁 打印出每次成功解决问题的方法遥 2.3 在路上
就是既没有到达失败出口袁 也没有达到成功出口袁 就是现在的位置袁 穷举所有的可能位置袁 判断和以前的 有没有冲突袁 如果没有冲突袁 则保存现场袁 递归试放下 一个位置遥 如果有冲突袁 则跳过去遥 例如可以向右走袁 向下走袁 那么就写 try 渊x,y+1) ; try (x+1,y)遥 3 新方法案例分析 3.1 案例 1:八皇后问题
下面用新的递归方法来打印出 92 种解的 C++递归 程序遥
#include<iostream> using namespace std; int place[9];//保存每行皇后的列位置 int num; int judge(int i,int j)//判断第 i 行第 j 列的皇后与前面可 //冲突 { int k; if(j>=9) //皇后到了第 9 列袁有冲突 return 1;
for(int i=1;i<=n;i++)//打出已成功的 k 个数 cout<<a[i]<<"--"; cout<<endl; return; } else { //没有结束袁试探 for(int i=1;i<=n;i++)//穷举第 k 个数的范围 if(judge(k,i)==0) //没有冲突袁成功放在 a[k] { a[k]=i;//i 成功放入 a[k] find(k+1);//试放 下一个值 } else continue;//有冲突袁跳过去袁继续穷举下一个 i } } int main() { cout<<"读入 n"<<endl; cin>>n; find(1);//第一位 开始试探 return 0; }

八皇后问题Python实现

八皇后问题Python实现

⼋皇后问题Python实现⼋皇后问题描述问题:国际象棋棋盘是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,则表明这是⼀条死路,返回上⼀层递归寻找其他办法;若来到的这⼀⾏是第九⾏(不存在第九⾏,只不过是说明前⼋⾏都已经正确配置,已经得到⼀个解决⽅案),这说明得到解决⽅案。

可以看到,寻找⼀⾏内皇后应该摆放的位置这是个递归过程,并且在进⼊递归时,应该要告诉这个过程的东西包括两个: 1. 之前皇后放置的状态, 2. 现在是第⼏⾏。

所以,递归主体函数可以设计为 EightQueen(board, row),其中board表⽰的是当前棋盘的状态(⽐如⼀个⼆维数组,0表⽰未放置,1表⽰放有皇后的状态)。

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