n皇后问题

n皇后问题
n皇后问题

n皇后问题是递归和回溯法的一个典型应用。问题描述如下:对于一个n×n的棋盘,要求在其中放入互不攻击的n个皇后。皇后的攻击范围包括:

1) 同一行

2) 同一列

3) 同一对角线(包括两个方向)

分析后可见,皇后之间互不攻击当且仅当满足下列条件:

1) 每一行只能有一个皇后

2) 每一列只能有一个皇后

3) 任意条对角线上面只能有一个皇后

若按照从左到右从上到下的顺序手动摆放皇后,会发现算法遵循的是回溯法的思想。于是我们遵循top-down design的顺序来设计整个算法和程序。

采用OOP的思想,先假设存在一个·表示棋盘格局的类queens,则定义回溯函数solve_from(queens configuration),configuration表示当前棋盘格局,算法不断扩展棋盘的当前格局(找到下一个非冲突位置),当找到一个解决方案时打印该方案。该递归函数采用回溯法求出所有解。main函数调用solve_from时传递的实参是一个空棋盘。

对于模拟棋盘的queens类,我们可以定义三个数据成员:

1) size:棋盘的边长,即大小

2) count:已放置的互不冲突的皇后数

3) array[][]:布尔矩阵,true表示当前格有皇后

这里需要稍加思考以便稍后可以简化程序:因为每行只能放一个皇后,从上到下,从左到右放,那么count个皇后占用的行为0——count-1。所以count还表示下一个皇后应该添加在哪一行。这样,add和remove操作的入口参数就只需要提供列号就行了,降低了耦合度:)

为了模拟棋盘操作,应该至少提供以下方法:

1) 初始化一个size大小的空棋盘queens(int size)

2) 插入一个非冲突的皇后add( int col )

3) 删除最新插入的皇后remove( int col )

4) 判断要插入的皇后是否与已存在的棋盘格局相冲突bool guarded( int col )

5) 判断是否棋盘已满bool finished( )

6) 若棋盘已满则打印棋盘格局print()

于是solve_from定义如下:

void solve_from( queens &configuration )

{

if( configuration.finished() )

configuration.print();

else

for( int i=0; i

if( !configuration.guarded( i ) )

{

configuration.add( i );

solve_from(configuration);

configuration.remove( i );

}

}

queens的方法实现如下:

static const int MAX_SIZE = 20

queens::queens( const int & size )

{

for( int i=0; i

for( int j=0; j

array[ i ][ j ] = false;

this->size = size;

count = 0;

}

void queens::add( const int & col )

{

array[ count++ ][ col ] = true;

}

void queens::remove( const int & col )

{

array[ --count ][ col ] = false;

}

关于guarded还有一点说明:

由于回溯法中的剪枝函数configuration.remove保证了每行只有一个皇后,我们是需要判断列冲突与对角线冲突的情况。而且由递归的顺序是从上到下从左到右,所以我们也不需要判断下方的列和对角线,也就是说只要判断三个方向:

current——top

current——upper-left

current——upper-right

工作量就减少了一半以上。

bool queens::guarded( const int & col )

{

bool gu = false;

// current——top

for( int i=0; !gu&&i

gu = array[ i ][ col ];

// current——up-left

for( i=1; !gu&&(count-i>=0)&&(col-i>=0); i++ )

gu = array[ count-i ][ col-i ];

// current——up-right

for( i=1; !gu&&(count-i>=0)&&(col+i<=size; i++ ) gu = array[ count-i ][ col+i ];

return gu;

}

bool queens::finished()

{

return count

}

bool queens::print()

{

static int num = 0;

++num;

cout<<"solution "<

for( int i=0; i

{

for( int j=0; j

cout<

cout<

}

cout<

}

#include

#include

#include

#define QUEENS 8

//!记录解的序号的全局变量。

int iCount = 0;

//!记录皇后在各列上的放置位置的全局数组。

int Site[QUEENS];

//!递归求解的函数。

void Queen(int n);

//!输出一个解。

void Output();

//!判断第n个皇后放上去之后,是否有冲突。

int IsValid(int n);

/*----------------------------Main:主函数。----------------------------*/

void main()

{

//!从第0列开始递归试探。

Queen(0);

//!按任意键返回。

getch();

}

/*-----------------Queen:递归放置第n个皇后,程序的核心!----------------*/

void Queen(int n)

{

int i;

//!参数n从0开始,等于8时便试出了一个解,将它输出并回溯。

if(n == QUEENS)

{

Output();

return;

}

//!n还没到8,在第n列的各个行上依次试探。

for(i = 1 ; i <= QUEENS ; i++)

{

//!在该列的第i行上放置皇后。

Site[n] = i;

//!如果放置没有冲突,就开始下一列的试探。

if(IsValid(n))

Queen(n + 1);

}

}

/*------IsValid:判断第n个皇后放上去之后,是否合法,即是否无冲突。------*/ int IsValid(int n)

{

int i;

//!将第n个皇后的位置依次于前面n-1个皇后的位置比较。

for(i = 0 ; i < n ; i++)

{

//!两个皇后在同一行上,返回0。

if(Site[i] == Site[n])

return 0;

//!两个皇后在同一对角线上,返回0。

if(abs(Site[i] - Site[n]) == (n - i))

return 0;

}

//!没有冲突,返回1。

return 1;

}

/*------------Output:输出一个解,即一种没有冲突的放置方案。------------*/ void Output()

{

int i;

//!输出序号。

printf("No.%-5d" , ++iCount);

//!依次输出各个列上的皇后的位置,即所在的行数。

for(i = 0 ; i < QUEENS ; i++)

printf("%d " , Site[i]);

printf("\n");

}

#include

#include

#include

using namespace std;

int *position; //放置的位置

int queen; //皇后数目

int count; //第N种可能性

//判断第n行是否放置皇后

bool SignPoint(int n)

{

for (int i=0;i

{

if (*(position+i) == *(position+n)) //该列已经放置过皇后了

return false;

if (abs(*(position+i) - *(position+n)) == n-i) //对角线已经放置过了

return false;

}

return true;

}

//设置皇后

void SetQueen(int n=0)

{

if (queen==n)

{

//该处可以改成自己想要的显示方式

printf("NO.%d: ",++count);

printf("\n");

for (int i=0;i

{

for (int j=0;j

{

if (j == position[i])

{

printf("* ");

}

else

{

printf("0 ");

}

}

printf("\n");

}

printf("\n");

return;

}

else

{

for (int i=0;i

{

position[n] = i;

if(SignPoint(n))//如果该位置放置皇后正确的话,则到下一行

{

SetQueen(n+1);

}

}

}

}

int main(int argc, char argv[])

{

cout<<"请输入皇后的总数:"<

cin>>queen;

position = (int*)malloc(sizeof(int));

SetQueen();

cout<<"摆放完毕"<

cin.get();

cin.get();

return 0;

}

八皇后算法c++源程序

#include

using namespace std;

#include

#include

#include

#define QUEENS 8 //改变QUEENS的值可以设置棋盘

int iCount=0; //!记录解的序号的全局变量。

int Site[QUEENS]; //!记录皇后在各列上的放置位置的全局数组。void Queen(int n); //!递归求解的函数。

void Output(); //!输出一个解。

int IsValid(int n); //!判断第n个皇后放上去之后,是否有冲突。

/*----------------------------Main:主函数。

----------------------------*/

void main()

{

Queen(0); //!从第0行开始递归试探。

//getch();

system("pause"); //!按任意键返回。

}

/*-----------------Queen:递归放置第n个皇后,程序的核

心!----------------*/

void Queen(int n)

{

int i;

if(n==QUEENS) //!参数n从0开始,等于8时便试出了一个解,将它输出并回溯。

{

Output();

return;

}

for(i=1;i<=QUEENS;i++) //!n还没到8,在第n行的各个列上依次试探。{

Site[n]=i; //!在该行的第i列上放置皇后。

if(IsValid(n)) //!如果放置没有冲突,就开始下一行的试探。

Queen(n+1);

}

}

/*------IsValid:判断第n个皇后放上去之后,是否合法,即是否无冲突。------*/

int IsValid(int n)

{

int i;

for(i=0;i

{

if(Site[i]==Site[n]) //!两个皇后在同一列上,返回0。

return 0;

if(abs(Site[i]-Site[n])==(n-i)) //!两个皇后在同一对角线上,返回0。

return 0;

}

return 1; //!没有冲突,返回1。

}

/*------------Output:输出一个解,即一种没有冲突的放置方案。

------------*/

void Output()

{

int i;

int j;

int n;

cout<<"输出的结果为:(数字结果显示为每一行的第几列)"<

cout<< endl;

cout<<"No."<<++iCount<<" 解法"<<" ";

for(i=0;i

cout<

cout<< endl;

cout<< endl;

cout<<"按任意键输出图形";

getch();

cout<< endl;

cout<< endl;

for(i=0;i

{

{n=Site[i];

for(j=1;j<=QUEENS;j++)

if(j==n)

cout<<"☆"<<" ";

else cout<<"■"<<" ";

}

cout<

}

cout<< endl;

system("pause");

system("cls"); }

回溯法之N皇后问题(C语言)

//回溯法之N皇后问题当N>10,就有点抽了~~ /*结果前total行每行均为一种放法,表示第i行摆放皇后的列位置,第total+1行,输出total*/ #include #include int n,stack[100]; //存当前路径 int total; //路径数 void make(int l) //递归搜索以stack[l]为初结点的所有路径 { int i,j; //子结点个数 if (l==n+1) { total=total+1; //路径数+1 for(i=1;i<=n;i++) printf("%-3d",stack[i]); //输出第i行皇后的列位置stack[i] printf("\n"); exit; //回溯(若试题仅要求一条路径,则exit改为halt即可)} for (i=1;i<=n;i++) { stack[l]=i; //算符i作用于生成stack[l-1]产生子状态stack[l]; if (!att(l,i)) make(l+1); } //再无算符可用,回溯 } int att(int l,int i) { int k; for (k=1;k

算法实验 递归回溯解八皇后问题

深圳大学实验报告 课程名称:算法分析与复杂性理论 实验项目名称:八皇后问题 学院:计算机与软件学院 专业:软件工程 指导教师:杨烜 报告人:学号:班级:15级软工学术型实验时间:2015-12-08 实验报告提交时间:2015-12-09 教务部制

一.实验目的 1.掌握选回溯法设计思想。 2.掌握八皇后问题的回溯法解法。 二.实验步骤与结果 实验总体思路: 根据实验要求,通过switch选择八皇后求解模块以及测试数据模块操作,其中八皇后模块调用摆放皇后函数模块,摆放皇后模块中调用判断模块。测试数据模块主要调用判断模块进行判断,完成测试。用一维数组保存每行摆放皇后的位置,根据回溯法的思想递归讨论该行的列位置上能否放置皇后,由判断函数Judge()判断,若不能放置则检查该行下一个位置。相应结果和过程如下所示(代码和结果如下图所示)。 回溯法的实现及实验结果: 1、判断函数 代码1: procedure BTrack_Queen(n) //如果一个皇后能放在第K行和X(k)列,则返回true,否则返回false。 global X(1:k);integer i,k i←1 while i0 do X(k)←X(k)+1 //移到下一个位置 while X(k)<=n and not Judge(k) do //判断能否放置皇后 X(k)←X(k)+1 repeat if X(k)<=n //找到一个位置 then if k=n //是一个完整的解吗

回溯法实验(n皇后问题)

算法分析与设计实验报告第六次实验

附录: 完整代码(回溯法) //回溯算法递归回溯n皇后问题#include #include #include #include"math.h" using namespace std; class Queen

{ friend int nQueen(int); //定义友元函数,可以访问私有数据 private: bool Place(int k); //判断该位置是否可用的函数 void Backtrack(int t); //定义回溯函数 int n; //皇后个数 int *x; //当前解 long sum; //当前已找到的可行方案数 }; int main() { int m,n; for(int i=1;i<=1;i++) { cout<<"请输入皇后的个数:"; //输入皇后个数 cin>>n; cout<<"皇后问题的解为:"<

八皇后问题的解决完整文档

工学院 数据结构课程设计报告设计题目:八皇后 2008 年 6 月25 日 设计任务书

摘要: 八皇后问题要求在一个8*8的棋盘上放上8个皇后,使得每一个皇后既攻击不到另外七个皇后,也不被另外七个皇后所攻击.按照国际象棋的规则,一个皇后可以攻击与之处在同一行或同一列或同一斜线上的其他任何棋子.因此,八皇后问题等于要求八个皇后中的任意两个不能被放在同一行或同一列或同一斜线上。 而本课程设计本人的目的也是通过用c++语言平台将一个8*8的棋盘上放上8个皇后,使得每一个皇后既攻击不到另外七个皇后,也不被另外七个皇后所攻击的92种结构予以实现.使用递归方法最终将其问题变得一目了然,更加易懂。 关键词:八皇后; c++; 递归法

目录 1. 课题综述 (1) 1.1课题的来源及意义 (1) 1.2面对的问题 (1) 2. 需求分析 (1) 2.1涉及到的知识 (2) 2.2软硬件的需求 (2) 2.3功能需求 (2) 3. 概要设计 (2) 4. 详细设计和实现 (3) 4.1算法描述及详细流程图 (3) 4.1.1算法描述 (3) 4.1.2算法流程图 (3) 5. 代码编写及详细注释 (4) 6. 程序调试 (8) 6.1调试过程、步骤及遇到的问题 (8) 7. 运行与测试 (8) 7.1运行演示 (8) 总结 (10) 致 (11)

参考文献 (12) .

1. 课题综述 1. 1课题的来源及意义 八皇后问题是一个古老而著名的问题,该问题是十九世纪著名的数学家高斯1850年提出的。 在国际象棋中,皇后是最有权利的一个棋子;只要别的棋子在它的同一行或同一列或同一斜线(正斜线或反斜线)上时,它就能把对方棋子吃掉。所以高斯提出了一个问题:在8*8的格的国际象棋上摆放八个皇后,使其不能相互攻击,即任意两个皇后都不能处于同一列、同一行、或同一条斜线上面,问共有多少种解法。 到了现代,随着计算机技术的飞速发展,这一古老而有趣的数学游戏问题也自然而然的被搬到了计算机上。运用所学计算机知识来试着解决这个问题是个锻炼和提高我自己编程能力和独立解决问题能力的好机会,可以使我增强信心,为我以后的编程开个好头,故我选择了这个有趣的课题。 1. 2 面对的问题 1)解决冲突问题: 这个问题包括了行,列,两条对角线; 列:规定每一列放一个皇后,不会造成列上的冲突; 行:当第I行被某个皇后占领后,则同一行上的所有空格都不能再放皇后,要把以I为下标的标记置为被占领状态; 2)使用数据结构的知识,用递归法解决问题。 2. 需求分析

n皇后问题算法实验报告

算法分析与设计实验报告 实验内容:N皇后问题 实验时间:2013.12.3 姓名:杜茂鹏 班级:计科1101 学号:0909101605

一、实验内容及要求 在n×n格的棋盘上放置彼此不受攻击的n个皇后,按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 二、实验目的 1.巩固和加深对回溯法的理解 2.了解递归和迭代法在回溯法中的应用 三、算法分析 1.理解皇后不被攻击的条件:n后问题等价于在n*n格的棋盘上放置n个皇后,任何两个皇后不能放在同一行或同一列或同一斜线上。 2.算法模块简要分析 用数组存储皇后的位置,将i设置为0. Int place(*x,n) :数组x[] 用来表示列数,n为皇后个数,用来判断皇后是否被攻击,判断的条件是(x[i]-x[n]==i-n||x[i]-x[n]==n-i||x[i]==x[n])即用来判断“同一行或同一列或同一斜线上”。 Int print(*x,n):打印皇后解的空间。 Int iniprint(*x,n):初始化打印函数,相当于对棋盘初始化。将可以放皇后的位置记为“1”,不放皇后的位置记为“0”。 Int Nqueen(int n):n皇后问题求解,如果满足一组可行解,sum++。Int i=0,如果x[i]>=n的时候即进行下一行,i++;当i=n时,

sum++;输出该组可行解的个数和位置的矩阵。并且i--,回溯到上一层继续搜索可行解。 四、运行结果及分析 1、三皇后没有可行解 2、 2.4个皇后有2个可行解 3.5皇后有10个可行解 五、源代码 #include static int n, sum=0;//可行解个数 static int locate[20]; int place(int k) {//判断是否在一条线上并返回0,1 for(int i=1;in){

第五组回溯算法(N皇后排列方法问题)

实训一 N皇后排列方法问题的回溯算法与实现 一、设计目的 1)掌握N皇后排列方法问题的回溯算法; 2)进一步掌握回溯算法的基本思想和算法设计方法; 二、设计内容 1.任务描述 1)算法简介 回溯法(探索与回溯法)是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再 走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。 2)N皇后排列方法问题简介 在N*N格的棋盘上放置彼此不受攻击的N个皇后.按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子.N后问题等价于在N*N格的棋盘上放置N个皇后,任何2个皇后不放在同一行或同一列或同一斜线上. 3)设计任务简介 对于回溯类似的问题。首先,要能理解该问题运用到的回溯的概念;其次,根据回溯相关的基本思想,找出相应的数学公式;最后,进行程序的设计和编写。 利用回溯的基本思想和计算步骤,有助于我们解决生活中遇到的各种数学问题。 4)问题分析 由于这是一个平面上棋子布局处理问题,因此,我们可以将问题看成是一个二维数组问题。给八个皇后分别编号为1,2,…,8,其中第i个皇后放置在第i行上,并这就解决了不同皇后分别摆放在 不同列的问题,这样又可以把问题简化为一个一维数组的问题,假设用一维数组x[i]来存放皇后所放 置的列,对于第i个皇后,假设它存放在x[i]列上,则对应的x数组应满足如下的条件:[2] 1)因为一共只有8列,故x[i]的取值只能取1到8之间的数。 2)因为不同的皇后只能粗放在不同的列上,则对于任意的i和j,应满足如果i!=j,则x[i]!=x[j] 3)因为不同的皇后不能存放在同一对角线上,故连接两个皇后的直线的斜率应不能等于正负1,而 连接任意第i个皇后和第j个皇后(i与j不同)的直线的斜率的计算公式为:(x[i]-x[j])/(i-j), 即(x[i]-x[j])/(i-j)!=±1,即:|x[i]-x[j]|!=| i-j | N皇后排列方法问题的表示方案

回溯法解八皇后问题

回溯法解八皇后问题 在N * N 格的棋盘上放置彼此不受攻击的N 个皇后。N个皇后问题等价于在N * N 格的棋盘上放置N 个皇后,任何2个皇后不在同一行或同一列或同一斜线上。当N等于8,就是著名的八皇后问题。 此问题是通过C语言程序编写的,在Turboc环境下完成实现的。输出结果见(输出结果。TXT文件) 详细代码为: /*///////////////////////////////////////////////////////////////////// /// /////The programming is a complex problem about the ways of queens./////// /////Programmer: Luo Xiaochun /////// /////Completed date: 2007.12 //////// /////V ersion number: Turboc 2.0 //////// /////////////////////////////////////////////////////////////////////// /*/ #include #include #define false 0 #define true 1 #define quesize 8 int gx[quesize+1]; int sum=0; int place( int k ); void print( int a[] ); void nqueens( int n ); FILE *fp; int main( ) { system("cls"); fp = fopen("outfile.txt", "w");

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

回溯算法与八皇后问题(N皇后问题) 1 问题描述 八皇后问题是数据结构与算法这一门课中经典的一个问题。下面再来看一下这个问题的描述。八皇后问题说的是在8*8国际象棋棋盘上,要求在每一行放置一个皇后,且能做到在竖方向,斜方向都没有冲突。更通用的描述就是有没有可能在一张N*N的棋盘上安全地放N个皇后? 2 回溯算法 回溯算法也叫试探法,它是一种系统地搜索问题的解的方法。回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试。 在现实中,有很多问题往往需要我们把其所有可能穷举出来,然后从中找出满足某种要求的可能或最优的情况,从而得到整个问题的解。回溯算法就是解决这种问题的“通用算法”,有“万能算法”之称。N皇后问题在N增大时就是这样一个解空间很大的问题,所以比较适合用这种方法求解。这也是N皇后问题的传统解法,很经典。 下面是算法的高级伪码描述,这里用一个N*N的矩阵来存储棋盘: 1) 算法开始, 清空棋盘,当前行设为第一行,当前列设为第一列 2) 在当前行,当前列的位置上判断是否满足条件(即保证经过这一点的行,列与斜线上都没 有两个皇后),若不满足,跳到第4步 3) 在当前位置上满足条件的情形: 在当前位置放一个皇后,若当前行是最后一行,记录一个解; 若当前行不是最后一行,当前行设为下一行, 当前列设为当前行的第一个待测位置;

若当前行是最后一行,当前列不是最后一列,当前列设为下一列; 若当前行是最后一行,当前列是最后一列,回溯,即清空当前行及以下各行的棋盘,然后,当前行设为上一行,当前列设为当前行的下一个待测位置; 以上返回到第2步 4) 在当前位置上不满足条件的情形: 若当前列不是最后一列,当前列设为下一列,返回到第2步; 若当前列是最后一列了,回溯,即,若当前行已经是第一行了,算法退出,否则,清空当前行及以下各行的棋盘,然后,当前行设为上一行,当前列设为当前行的下一个待测位置,返回到第2步; 算法的基本原理是上面这个样子,但不同的是用的数据结构不同,检查某个位置是否满足条件的方法也不同。为了提高效率,有各种优化策略,如多线程,多分配内存表示棋盘等。 为了便于将上述算法编程实现,将它用另一种形式重写: Queen() Loop: if check_pos(curr_row, curr_col) == 1 then put_a_queen(curr_row, curr_col); if curr_row == N then record_a_solution(); end if; if curr_row != N then curr_row = curr_row + 1; curr_col = 1; else if curr_col != N then curr_col = curr_col + 1; else backtrack(); end if; end if; else if curr_col != N then

8皇后问题matlab算法

M文件 function PlaceQueen(row,matrix,N)%回溯法放置皇后 if row>N PrintQueen(N,matrix);%打印棋盘 else for col=1:N matrix(row,col)=1; if row==1||Conflict(row,col,N,matrix)%检测是否冲突 PlaceQueen(row+1,matrix,N); end matrix(row,col)=0; end end %子函数:检测冲突 function result=Conflict(row,col,N,matrix)%检测是否冲突 result=1; for i=1:row-1 for j=1:N if matrix(i,j)==1 if ((j==col)||(abs(row-i)==abs(col-j)))%是否产生冲突:在同一直线,斜线上 result=0; break; end end end if result==0 break; end end %子函数:打印棋盘信息

function PrintQueen(N,matrix) global solutionNum; %定义全局变量,来累积方法数 solutionNum=solutionNum+1; disp(['第',num2str(solutionNum),'种方法:']) disp(matrix) 脚本文件 clear all clc global solutionNum; solutionNum=0;%全局变量记录方法数 N=8;%皇后个数 matrix=zeros(N);%存储皇后位置信息 PlaceQueen(1,matrix,N)%调用放置方法

回溯法实验(n皇后问题)(迭代法)

算法分析与设计实验报告第三次附加实验

附录: 完整代码(回溯法) //回溯算法递归回溯n皇后问题#include #include #include #include"math.h" using namespace std; class Queen

{ friend int nQueen(int); //定义友元函数,可以访问私有数据 private: bool Place(int k); //判断该位置是否可用的函数 void Backtrack(int t); //定义回溯函数 int n; //皇后个数 int *x; //当前解 long sum; //当前已找到的可行方案数 }; int main() { int m,n; for(int i=1;i<=1;i++) { cout<<"请输入皇后的个数:"; //输入皇后个数 cin>>n; cout<<"皇后问题的解为:"<

实验报告:回溯法求解N皇后问题(Java实现)

实验报告 一、实验名称:回溯法求解N皇后问题(Java实现) 二、学习知识: 回溯法:也称为试探法,它并不考虑问题规模的大小,而是从问题的最明显的最小规模开始逐步求解出可能的答案,并以此慢慢地扩大问题规模,迭代地逼近最终问题的解。这种迭代类似于穷举并且是试探性的,因为当目前的可能答案被测试出不可能可以获得最终解时,则撤销当前的这一步求解过程,回溯到上一步寻找其他求解路径。 为了能够撤销当前的求解过程,必须保存上一步以来的求解路径,这一点相当重要。 三、问题描述 N皇后问题:在一个 N * N 的国际象棋棋盘中,怎样放置 N 个皇后才能使 N 个皇后之间不会互相有威胁而共同存在于棋局中,即在 N * N 个格子的棋盘中没有任何两个皇后是在同一行、同一列、同一斜线上。 深度优先遍历的典型案例。 四、求解思路 1、求解思路:最容易想到的方法就是有序地从第 1 列的第 1 行开始,尝试放上一个皇后,然后再尝试第 2 列的第几行能够放上一个皇后,如果第 2 列也放置成功,那么就继续放置第 3 列,如果此时第 3 列没有一行可以放置一个皇后,说明目前为止的尝试是无效的(即不可能得到最终解),那么此时就应该回溯到上一步(即第 2 步),将上一步(第 2 步)所放置的皇后的位置再重新取走放在另一个符合要求的地方…如此尝试性地遍历加上回溯,就可以慢慢地逼近最终解了。 2、需要解决的问题:如何表示一个 N * N 方格棋盘能够更有效?怎样测试当前所走的试探路径是否符合要求?这两个问题都需要考虑到使用怎样的数据结构,使用恰当的数据结构有利于简化编程求解问题的难度。 3、我们使用以下的数据结构: int column[col] = row 表示第 col 列的第 row 行放置一个皇后 boolean rowExists[i] = true 表示第 i 行有皇后 boolean a[i] = true 表示右高左低的第 i 条斜线有皇后(按→↓顺序从1~ 2*N -1 依次编号) boolean b[i] = true 表示左高右低的第 i 条斜线有皇后(按→↑顺序从1~ 2*N -1 依次编号) 五、算法实现 对应这个数据结构的算法实现如下:

八皇后问题讲解

计算机科学与技术专业 数据结构课程设计报告设计题目:八皇后问题

目录 1需求分析 (3) 1.1功能分析 (3) 1.2设计平台 (4) 2概要设计 (4) 2.1算法描述 (5) 2.2算法思想 (6) 2.3数据类型的定义 (6) 3详细设计和实现 (7) 3.1算法流程图 (7) 3.2 主程序 (7) 3.3 回溯算法程序 (8) 4调试与操作说明 (10) 4.1调试情况 (10) 4.2操作说明 (10) 5设计总结 (12) 参考文献 (13) 附录 (13)

1需求分析 1.1功能分析 八皇后问题是一个古老而著名的问题,该问题是十九世纪著名的数学家高斯1850年提出的,并作了部分解答。高斯在棋盘上放下了八个互不攻击的皇后,他还认为可能有76种不同的放法,这就是有名的“八皇后”问题。 在国际象棋中,皇后是最有权利的一个棋子;只要别的棋子在它的同一行或同一列或同一斜线(正斜线或反斜线)上时,它就能把对方棋子吃掉。所以高斯提出了一个问题:在8*8的格的国际象棋上摆放八个皇后,使其不能相互攻击,即任意两个皇后都不能处于同一列、同一行、或同一条斜线上面,问共有多少种解法。现在我们已经知道八皇后问题有92个解答。 1、本演示程序中,利用选择进行。程序运行后,首先要求用户选择模式,然后进入模式。皇后个数设0

回溯算法解决N皇后问题实验及其代码

实验报告4 回溯算法 实验4 回溯算法解决N皇后问题 一、实验目的 1)掌握回溯算法的实现原理,生成树的建立以及限界函数的实现; 2)利用回溯算法解决N皇后问题; 二、实验内容 回溯算法解决N皇后问题。 三、算法设计 1)编写限界函数bool PLACE(int k,int x[]),用以确定在k列上能否放置皇后; 2)编写void NQUEENS(int n)函数用以摆放N个皇后; 3)编写主函数,控制输入的皇后数目; 4)改进和检验程序。 四、程序代码 //回溯算法解决N皇后问题的c++程序 #include #include using namespace std; int count=0; //皇后摆放的可能性 bool PLACE(int k,int x[]);//限界函数 void NQUEENS(int n);//摆放皇后 int main() { int queen; cout<<"先生(女士)请您输入皇后的总数,谢谢!:"<>queen; NQUEENS(queen); cout<<"所有可能均摆放完毕,谢谢操作"<

void NQUEENS(int n){ /*此过程使用回溯算法求出在一个n*n棋盘上放置n个皇后,使其即不同行,也不同列,也不在同一斜角线上*/ int k, *x=new int[n];//存放皇后所在的行与列 x[0]=0; k=0; while (k>=0&&k

回溯法n皇后问题

1、方法思想 回溯法是一个既带有系统性又带有跳跃性的搜索算法。它在问题的解空间树中,按深度优先策略,从根节点出发搜索解空间树。算法搜索至解空间树的任何一结点时,先判断该结点是否包含问题的解。如果肯定不包含,则跳过对以该结点为根的子树的搜索,逐层向其祖先结点回溯;否则进入该子树,继续按深度优先策略搜索。 代码实现: class Queen { friend int nQueen(int) private: bool Place(int k); void Backtrack(int t); int n, //皇后个数 *n; //当前解 long sum; //当前已找到的可行方案数 }; bool Queen::Place(int k) { for (int j=1;jn) sum++; //达到叶结点 else for (int i=1;i<=n;i++) { //搜索子结点 x[t]=i; //进入第i个子结点 if (Place(t)) Backtrack(t+1); } } int nQueen(int n) { Queen X; //初始化X X.n=n; X.sum=0; int *p=new int [n+1]; for(int i=0;i<=n;i++) p[i]=0; X.x=p; X.Backtrack(1); //对整个解空间回溯搜索

八皇后问题 C语言程序设计

八皇后问题学 2012年 9 月 5 日 目录 一、选题 1.1背景知识 (2) 1.2设计目的与要求 (2) 二、算法设计 2.1问题分析 (3) 2.2算法设计 (3) 三、详细设计 3.1源程序清单 (4) 四、调试结果及分析 4.1调试结果 (6) 4.2调试分析 (7) 五、课程设计总结 5.1总结及体会 (7) 六、答辩 6.1答辩记录 (8) 6.2教师意见 (8) 一、选题及背景知识 1.1 背景知识

在国际象棋中,皇后是一个威力很大的棋子,她可以“横冲直撞”(在正负或垂直方向走任意步数),也可以“斜刺冲杀”(在正负45度方向走任意步数),所以在8*8的棋盘上要布互相不受攻击的皇后,最多只能布八个,共92种布法,再也不能有别的布法了——这就是著名的八皇后问题 在8*8的国际象棋棋盘上,放置八个皇后,使得这八个棋子不能互相被对方吃掉。也就是说一个皇后可以攻击与之处在同一行或同一列或同一斜线上的其他任何棋子.因此,八皇后问题等于要求八个皇后中的任意两个不能被放在同一行或同一列或同一斜线上。 1.2 设计要求 要求:·判断在国际象棋中,能否在空棋盘上摆放8个皇后,并使其中任意两个皇后不能在同一行,同一列或同一对角线上。 ·编写完整的摆放八皇后问题的程序 ·具体要求第一个皇后的起始位置由键盘输入 二、算法设计 2.1问题分析 设计——图形表示下图中,Q代表皇后 假设在第k列上找到合适的位置放置一个皇后,要求它与第1——k-1列上的皇后不同行、列、对角线;可以从图上找到规律:不同列时成立,皇后放在第k列上;讨论行时,第j个皇后的位置(a[j] ,j)要与(i,k)位置的皇后不同行;如果同在/斜线上,行列值之和相同;如果同在\斜线上,行列值之差相同;如果斜线不分方向则同一斜线上两皇后的行号之差的绝对值与列号之差的绝对值相同,可表示为(|a[j]-i|=|j-k|)。 2.2 算法设计 利用计算机运行速度快的特点,采用枚举法,逐一尝试各种摆放方式,来判断最终摆法。其中判断是否同在对角线上用到了:行数差的绝对值与列数差的绝对值相等,

人工智能课程设计报告-n皇后问题解读

课程:人工智能课程设计报告 班级: 姓名: 学号: 指导教师:赵曼 2015年11月

人工智能课程设计报告 课程背景 人工智能(Artificial Intelligence),英文缩写为AI。它是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学。人工智能是计算机科学的一个分支,它企图了解智能的实质,并生产出一种新的能以人类智能相似的方式做出反应的智能机器,该领域的研究包括机器人、语言识别、图像识别、自然语言处理和专家系统等。人工智能从诞生以来,理论和技术日益成熟,应用领域也不断扩大,可以设想,未来人工智能带来的科技产品,将会是人类智慧的“容器”。 人工智能是对人的意识、思维的信息过程的模拟。人工智能不是人的智能,但能像人那样思考、也可能超过人的智能。 人工智能是一门极富挑战性的科学,从事这项工作的人必须懂得计算机知识,心理学和哲学。人工智能是包括十分广泛的科学,它由不同的领域组成,如机器学习,计算机视觉等等,总的说来,人工智能研究的一个主要目标是使机器能够胜任一些通常需要人类智能才能完成的复杂工作。但不同的时代、不同的人对这种“复杂工作”的理解是不同的。 人工智能是计算机学科的一个分支,二十世纪七十年代以来被称为世界三大尖端技术之一(空间技术、能源技术、人工智能)。也被认为是二十一世纪三大尖端技术(基因工程、纳米科学、人工智能)之一。这是因为近三十年来它获得了迅速的发展,在很多学科领域都获得了广泛应用,并取得了丰硕的成果,人工智能已逐步成为一个独立的分支,无论在理论和实践上都已自成一个系统。 人工智能是研究使计算机来模拟人的某些思维过程和智能行为(如学习、推理、思考、规划等)的学科,主要包括计算机实现智能的原理、制造类似于人脑智能的计算机,使计算机能实现更高层次的应用。人工智能将涉及到计算机科学、心理学、哲学和语言学等学科。可以说几乎是自然科学和社会科学的所有学科,其范围已远远超出了计算机科学的范畴,人工智能与思维科学的关系是实践和理论的关系,人工智能是处于思维科学的技术应用层次,是它的一个应用分支。从思维观点看,人工智能不仅限于逻辑思维,要考虑形象思维、灵感思维才能促进人工智能的突破性的发展,数学常被认为是多种学科的基础科学,数学也进入语言、思维领域,人工智能学科也必须借用数学工具,数学不仅在标准逻辑、模糊数学等范围发挥作用,数学进入人工智能学科,它们将互相促进而更快地发展。

八皇后问题的解决完整文档

淮阴工学院 数据结构课程设计报告 设计题目:八皇后 系(院):计算机工程系 专业:信息安全 班级:信息 1 0 6 学生姓名: 叶青学号:1061303127 指导教师:张亚红寇海洲胡荣林夏森 学年学期: 2007 ~ 2008 学年第 2 学期 2008 年 6 月25 日

设计任务书

摘要: 八皇后问题要求在一个8*8的棋盘上放上8个皇后,使得每一个皇后既攻击不到另外七个皇后,也不被另外七个皇后所攻击.按照国际象棋的规则,一个皇后可以攻击与之处在同一行或同一列或同一斜线上的其他任何棋子.因此,八皇后问题等于要求八个皇后中的任意两个不能被放在同一行或同一列或同一斜线上。 而本课程设计本人的目的也是通过用c++语言平台将一个8*8的棋盘上放上8个皇后,使得每一个皇后既攻击不到另外七个皇后,也不被另外七个皇后所攻击的92种结构予以实现.使用递归方法最终将其问题变得一目了然,更加易懂。 关键词:八皇后; c++; 递归法

目录 1. 课题综述 (1) 1.1课题的来源及意义 (1) 1.2面对的问题 (1) 2. 需求分析 (1) 2.1涉及到的知识 (1) 2.2软硬件的需求 (1) 2.3功能需求 (2) 3. 概要设计 (2) 4. 详细设计和实现 (2) 4.1算法描述及详细流程图 (2) 4.1.1算法描述 (3) 4.1.2算法流程图 (3) 5. 代码编写及详细注释 (4) 6. 程序调试 (7) 6.1调试过程、步骤及遇到的问题 (7) 7. 运行与测试 (7) 7.1运行演示 (7) 总结 (9) 致谢 (10) 参考文献 (11) .

回溯法求N皇后问题

Tree-回溯法求N皇后问题 #include #include #define N 4 //N皇后 typedef int Chessboard[N + 1][N + 1]; //第0号位置不用 bool check(Chessboard cb, int i, int j) { //看棋盘cb是否满足合法布局 int h, k; int m = i + j, n = i - j; for(h=1; hn时,求得一个合法的布局,输入之。*/ void trial(int i, Chessboard &cb) { int j; if(i > N) printfChessboard(cb); else { for(j=1; j<=N; j++) { cb[i][j] = 1; if(check(cb, i, j)) trial(i + 1, cb); cb[i][j] = 0; } } } void main() { int i, j; Chessboard cb; for(i=1; i<=N; i++) for(j=1; j<=N; j++) cb[i][j] = 0; //必须初始化,它的默认值不是0

数据结构课程设计之_八皇后问题

课程设计报告 课程名称数据结构课程设计 课题名称八皇后问题演示 专业通信工程 班级通信工程1081 学号201013120103 姓名刘献文 指导教师田娟秀郭芳 2012年7 月 6 日

湖南工程学院 课程设计任务书 课程名称数据结构 课题八皇后问题演示 专业班级通信工程1081 学生姓名刘献文 学号201013120103 指导老师田娟秀郭芳 审批 任务书下达日期2012 年7 月 1 日 任务完成日期2012 年7 月 6 日

1设计内容与设计要求 1.1设计内容 (4)课题四:八皇后问题演示 八皇后问题是一个古老而著名的问题,是回溯算法的典型例题。该问题是十九世纪著名的数学家高斯1850年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。 设计思路:解决8皇后时,在安放第i行皇后时,需要在列的方向从1到n试 探(j =1,…, n):首先在第j列安放一个皇后,如果在列、主对角线、次对角线方 向有其它皇后,则出现攻击,撤消在第j列安放的皇后。如果没有出现攻击,在第 j列安放的皇后不动,递归安放第i+1行皇后。 对于八皇后问题的实现,如果结合动态的图形演示,则可以使算法的描述更形象、更生动。要求用Turbo C或VC6.0 MFC实现的八皇后问题的图形程序,能够演示全部的92组解。 1.2 选题方案: 所选题目根据学号确定,学号模6加1,即(学号%6+1)。如你的学号为9,则 所选题目号为:9%6+1=(题目4)。注意,所有的课题都要求用图形方式演示步骤 和结果。同学们可以自己针对数据结构课程中所讲算法来设计一个演示过程的算法。 1.3设计要求: 1.3.1 课程设计报告规范 (1)需求分析 a.程序的功能。 b.输入输出的要求。 (2)概要设计 a.程序由哪些模块组成以及模块之间的层次结构、各模块的调用关系;每个模块 的功能。

n皇后问题算法设计

算法设计及分析

n皇后问题---回溯求解 国际象棋中皇后威力很大,它可以象“车”一样沿直线上下或左右移动;也可以如同 “象”那样沿着斜线移动。双方的皇后是不能在同一行或同一列或同一斜线上对持的。那么, 在一张空白的国际象棋盘上最多可以放上几个皇后并且不让它们互相攻击呢?这个问题是伟 大数学家高斯在十九世纪中期提出来的,并作了部分解答。高斯在棋盘上放下了N个互不攻 击的皇后,他还认为可能有N种不同的放法,这就是有名的“N皇后”问题。如果你动手试试, 就一定会发现开头几颗皇后很容易放置,越到后来就越困难。由于我们的记忆有限,很可能 在某个位置放过子后来证明不行取消了,但是以后又重新放上子去试探,这样就会不断地走 弯路,花费大量的精力。因此,必须找到一个简易有效、有条不紊的法则才行。 回溯法的基本思想: 对于用回溯法求解的问题,首先要将问题进行适当的转化,得出状态空间树。这棵树的 每条完整路径都代表了一种解的可能。通过深度优先搜索这棵树,枚举每种可能的解的情况; 从而得出结果。在深度优先搜索的过程中,不断的将每个解(并不一定是完整的,事实上这 也就是构造约束函数的意义所在)与约束函数进行对照从而删除一些不可能的解,这样就不 必继续把解的剩余部分列出从而节省部分时间。 不妨以8皇后为例,设8皇后为x i,她们分别在第i行(i=1,2,3,4,5,6,7,8),这样问 题的解空间就是一个8个皇后所在列的序号,为n元一维向量(x1,x2,,x3,x4,x5,x6,x7,x8),搜 索空间是1≤x i≤8(i=1,2,3,4,5,6,7,8),共88个状态。约束条件是8个点 (1,x1),(2,x2),(3,x3),(4,x4),(5,x5),(6,x6),(7,x7),(8,x8)不在同一列和同一对角线上。虽 然问题共有88个状态,但算法不会真正地搜索这么多的状态,因为回溯法采用的是“走不通 就掉头”的策略,而形如(1,1,x3,x4,x5,x6,x7,x8)的状态共有86个,由于1,2号皇后在同一 列不满足约束条件,回溯后这些状态是不会搜索的。 算法设计: 我们用三个数组c,b,d分别记录棋盘上的n个列,2n-1个住对角线和2n-1个副对角线的 占用情况。用i,j分别表示皇后所在的行列,用表达式i-j+n对主对角线编号,范围是1~2n-1, 用i+j为负对角线编号,范围为2~2n. 程序代码: #include"stdio.h" int a[20],b[20],c[40],d[40],n,i,k; int t=0; //t记录解的个数 void output() { t=t+1; printf("第%d个解:",t); for(k=1;k<=n;k++) printf("%d",a[k]); printf("\n"); } void find(int i) { int j; for(j=1;j<=n;j++) //第i个皇后有n种可能位置 if(b[j]==0&&c[i+j]==0&&d[i-j+n]==0) //判断位置是否冲突 {a[i]=j; //摆放皇后 b[j]=1; //占领第j列 c[i+j]=1;//占领两个对角线 d[i-j+n]=1; if(i

相关文档
最新文档