八皇后问题的实现(从简单到难得各种解法)

八皇后问题的实现(从简单到难得各种解法)
八皇后问题的实现(从简单到难得各种解法)

八皇后问题的实现(C语言)

八皇后问题主要靠回溯的方法实现, 与迷宫的实现相似, 但又困难了一些. 如迷宫的路径不因为上一步而改变, 八皇后的每一步都受约束于以前的步数, 并且, 迷宫只要找出一条路径就行,但八皇后则有很多的解法. 等等.

#include

#define N 8 // 定义棋盘的格数, 通过改变,也可以是4皇后, 16皇后, 9皇后什么的.

int chess[N][N] = {0}; // 棋盘

int count = 0; // 有多少种放法

intcanput(int row, int col) // 确定某一格能不能放

{

inti,j;

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

{

if(chess[i][col] == 1) //有同列的

{

return 0;

}

for(j = 0; j < N; j++)

{

if(chess[row][j]==1) //有同行的

{

return 0;

}

if(((i-row)==(j-col)||(i-row)==(col-j))&&chess[i][j]==1) // 对角线上有的

{

return 0;

}

}

}

return 1;

}

void print_chess() // 打印放置的方案

{

int i, j;

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

{

for(j = 0; j < N; j++)

{

printf("%d ", chess[i][j]);

}

printf("\n");

}

printf("\n");

}

int put(int row) // 放置棋子, row是从哪一行开始, 通常是0 {

int j, s;

for(j = 0; j < N; j++) // 此一行的每一个格子都要试试能不能放{

if(canput(row, j)) // 假如这格能放的话

{

chess[row][j] = 1; // 放置

if(row == N-1) // 已经到了最后一行, 那么肯定成功

******************************************************

{

count = count +1;

print_chess();

chess[row][j] = 0; //成功后, 寻找下一种方法

continue;

}

s = put(row+1); // 放置下一行的

if(s == 0) // 假如下一行不能放

{

chess[row][j] = 0; // 那么这格是放错了的, 清除

continue; // 找本行的下一个方格

}

else

{

break;

}

}

}

if(j==N) // 如果这一行的每个空格都不能放置

{

return 0; // 那么本行放置失败

}

else

{

return 1; // 本行放置成功

}

}

int main()

{

int s ;

s = put(0); // 放置

printf("the number of put way is %d\n", count); //打印信息

return 0;

}

这个程序有个奇怪的地方, 就是在有星号的那一行, 当把chess[row][j] = 0, continue;两句去掉时,发现程序依然能正常运行. 原因就是: 当行比列多时,假如皇后是的数目是列那么多, 是肯定放不成功的, 所以, 当程序要在最后一行的下一行放皇后时,怎么放也不成功,所以, 程序会不断调整以前的方法,但打印信息却在这里执行, 所以能打出正确信息. 但不建议去掉, 因为操作未知内存终究不是件好事.

盲目的枚举法

#include

#include

int check(int a[],int n)

{inti,j;

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

for(j=1;j<=i-1;j++)

if ((a[i]==a[j])||(abs(a[i]-a[j])==abs(i-j))) return(0);

return(1);

}

void queen1( )

{

int i;

int a[9];

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(a,8)==0)

continue;

else

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

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

printf("\n");

}

}

int main(intargc, char** argv) {

queen1();

return 0;

}

#include

#include

int check(int a[],int n)

{int i;

for(i=1;i<=n-1;i++)

if ((a[i]==a[n])||(abs(a[i]-a[n])==abs(i-n))) return(0);

return(1);

}

void queen1( )

{ int i;

int a[9];

for(a[1]=1;a[1]<=8;a[1]++)

for(a[2]=1;a[2]<=8;a[2]++)

{ if(check(a,2)==0)

continue;

for(a[3]=1;a[3]<=8;a[3]++)

{ if(check(a,3)==0)

continue;

for(a[4]=1;a[4]<=8;a[4]++)

{ if(check(a,4)==0)

continue;

for(a[5]=1;a[5]<=8;a[5]++)

{ if(check(a,5)==0)

continue;

for(a[6]=1;a[6]<=8;a[6]++)

{if(check(a,6)==0)

continue;

for(a[7]=1;a[7]<=8;a[7]++)

{ if(check(a,7)==0) continue;

for(a[8]=1;a[8]<=8;a[8]++){

{ if(check(a,8)==0) continue;

else

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

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

printf("\n");

}

}}}}}}}}

int main(intargc, char** argv) {

queen1();

return 0;

加约束的递归

#include

#include

int a[9] = {0};

int n = 8, count = 0;

int check(int a[],int n)

{inti,j;

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

for(j=1;j<=i-1;j++)

if ((a[i]==a[j])||(abs(a[i]-a[j])==abs(i-j)))

return(0);

return(1);

}

void Queens8(int k) //参数k:递归摆放第k个皇后

{

int i = 0;

if (k > n) //k>n:即k>8表示最后一个皇后摆放完毕

{ printf("第%d种情况:",++count);

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

printf("(%d,%d) ",i,a[i]);//打印情况

printf("\n");

}else //8个皇后未全部摆放完毕

{ for (i = 1; i <= n; i++)//摆放第k个皇后时

{ //依次从列顶端开始搜索,一直到列底端,直到找到合适位置,如果未找到,自动返回上层递归

a[k] = i;

if (check(a,k))//不冲突

Queens8(k+1);//递归摆放下一个皇后

} } return; }

main()

{

Queens8(1);

}

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行找到一个不受任何已经现有皇后攻击的位置,而第五列,我们会发现找不到皇后的安全位置了,前面四列的摆放如下:

深圳大学实验报告 课程名称:算法分析与复杂性理论 实验项目名称:八皇后问题 学院:计算机与软件学院 专业:软件工程 指导教师:杨烜 报告人:学号:班级: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 //是一个完整的解吗

工学院 数据结构课程设计报告设计题目:八皇后 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. 需求分析

数据结构实验报告 实验名称:实验二——利用栈结构实现八皇后问题 学生姓名: 班级: 班内序号: 学号: 日期:2013年11月21日 1.实验要求 (1)实验目的 通过选择下面五个题目之一进行实现,掌握如下内容: 进一步掌握指针、模板类、异常处理的使用 掌握栈的操作的实现方法 掌握队列的操作的实现方法 学习使用栈解决实际问题的能力 学习使用队列解决实际问题的能力 (2)实验内容 利用栈结构实现八皇后问题。 八皇后问题19世纪著名的数学家高斯于1850年提出的。他的问题是:在8*8的棋盘上放置8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列、同一斜线上。请设计算法打印所有可能的摆放方法。 ①可以使用递归或非递归两种方法实现 ②实现一个关键算法:判断任意两个皇后是否在同一行、同一列和同一斜线。 (3)代码要求 ①必须要有异常处理,比如删除空链表时需要抛出异常; ②保持良好的编程的风格: 代码段与段之间要有空行和缩近 标识符名称应该与其代表的意义一致 函数名之前应该添加注释说明该函数的功能 关键代码应说明其功能 ③递归程序注意调用的过程,防止栈溢出 2. 程序分析 2.1 存储结构 栈(递归):

2.2 关键算法分析 (1)递归 void SeqStack::PlaceQueen(int row) //在栈顶放置符合条件的值的操作,即摆放皇后{ for (int col=0;col::Judgement() { for(int i=0;i

流程图 八皇后问题算法分析 在这个问题中首先定义的是一个用于构造界面的二位数组a【i】【j】和一个用于判断的表头数组number【】。在开始进行八皇后棋子排列的时候,首先对行进行递增循环,即i初始值为0,每次i++,i最大值为8的循环。在每次循环中产生一个小于8的随机数q,然后判断表头数组number【】中number【q】位置的值是否为1,如果不是,则在二维数组a【i】【q】位置上打印表示棋子的“K”;如果为1,则返回产生随机数的步骤继续产生随机数。在循环到i>8时,跳出循环,这时候一个完整的八皇后排列也就出来了。 源代码: package queen; import java.awt.*; import java.awt.event.*; class equeen extends Frame implements ActionListener{ //构造界面和定义数组 Button enter; Button clean; Button exit; int number[] = new int[8]; int i,j,q; Label a[][] = new Label[8][8]; equeen(String s){ GridLayout grid; grid = new GridLayout(9,8); setLayout(grid); enter = new Button("begin"); clean = new Button("clean");

exit = new Button("esit"); for(int i = 0;i<8;i++){ for(int j = 0;j<8;j++){ a[i][j] = new Label(); if((i+j)%2==0)a[i][j].setBackground(Color.yellow); else a[i][j].setBackground(Color.gray); add(a[i][j]); } } for(int i = 0;i<8;i++){ number[i] = 0;//初始化判断数组 } add(enter); add(clean); add(exit); enter.addActionListener(this); clean.addActionListener(this); exit.addActionListener(this); setBounds(100,100,300,300); setVisible(true); validate(); } public void actionPerformed(ActionEvent e){ if(e.getSource()==enter){ for(int i =0;i<8;i++){ for(int j=0;j<8;j++){ a[i][j].setText(""); } } for(int i =0;i<8;i++){ while(true){ q = (int)(Math.random()*8); if(number[q]==0){ a[i][q].setText("K"); number[q] = 1; break; } else if(number[q]!=0) continue; } } for(int i = 0;i<8;i++){ number[i] = 0; } }

淮阴工学院 数据结构课程设计报告设计题目:八皇后 2008 年 6 月25 日 设计任务书 课题 名称 八皇后 设计目的1.用c++语言平台将一个8*8的棋盘上放上8个皇后,使得每一个皇后既 攻击不到另外七个皇后,也不被另外七个皇后所攻击的92种结构予以实现. 2.通过这次课程设计,提高自己的编程能力,熟悉c++的编程坏境,为以后的程 序开发打下基础.

实验环境1)系统要求:win98以上操作系统;2)语言平台:tc++或vc++6.0;3)执行文件:八皇后.exe 任务要求试编写程序实现将八个皇后放置在国际象棋棋盘的无冲突的位置上的算法,并给出所有的解。 工作进度计划 序号起止日期工作内容 1 2008.6.23~2008.6.24查阅相关内容 2 2008.6.24~2008.6.25编写代码及实习报告 3 2008.6.25~2008.6.26完善课程设计报告 4 2008.6.26~2008.6.27答辩 指导教师(签章): 2008 年 6 月30 日

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

八皇后问题 问题描述: 在一个8×8的棋盘里放置8个皇后,要求每个皇后两两之间不相冲突 (在每一横列,竖列,斜列只有一个皇后)。 求解: 标题: 八皇后问题的解(回溯法程序代码) 发信站: 网易虚拟社区(Fri Jul 14 10:06:52 2000),站内信件 以前上学的时候,写8皇后程序的时候偷懒用最笨的算法,在8086上计算十皇后的时候,我放了张纸条,说明计算机正在运行,然后去吃饭,吃完以后,才看到结果。前几天,刚好有空,所以重写了一次,以补当年的遗憾。 #include "stdio.h" int attacked(int *array,int position){ int flag=-1; float step; if(position==1) return flag; for(step= 1.00;step

(array+(int)step)-*(array+position))/(step-position))==-1){ flag=1; break;}} return flag;}void main(void){ int countSum,queenSum,printCount,*queenArray,queenPosition=0; int tempArray[20]={66,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; countSum=1; queenArray=tempArray; printf("input you queenSum here: "); scanf("%d",&queenSum); fflush(stdin); if(queenSum<4){ printf("the %d queen's sum is 0\n",queenSum); return;}for(;;){ if(countSum=queenSum){ if(*(queenArray+countSum-1)

1.实验要求 【实验目的】 1、进一步掌握指针、模板类、异常处理的使用 2、掌握栈的操作的实现方法 3、掌握队列的操作的实现方法 4、学习使用栈解决实际问题的能力 5、学习使用队列解决实际问题的能力 【实验内容】 利用栈结构实现八皇后问题。 八皇后问题19世纪著名的数学家高斯于1850年提出的。他的问题是:在8*8的棋盘上放置8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列、同一斜线上。请设计算法打印所有可能的摆放方法。 提示: 1、可以使用递归或非递归两种方法实现 2、实现一个关键算法:判断任意两个皇后是否在同一行、同一列和同一斜线上2. 程序分析 2.1 存储结构 存储结构:栈(递归) 2.2 关键算法分析 【设计思想】 由于八皇后问题,可以分解成算法相同的子问题,所以使用递归的方法 【伪代码】 1、输入皇后个数n 2、k=1 3、判断k是否大于n 3.1 是:打印一组可能 3.2 否:循环行位置1~n 判断该位置是否符合要求,若符合记录q[k]的坐标y值 k+1 重复3 【关键算法】 1、递归 void Queen::Queens(int k,int n)

{ int i; if(k>n) { Print(n); count(); } else { for(i=1;i<=n;i++) if(Isavailable(i,k)) //判断该行中该位置放置‘皇后’是否符合要求 { q[k]=i; //记录改行中该点的位置 Queens(k+1,n); //放置下一行的‘皇后’ } } } 2、判断皇后放置位置是否符合要求 bool Queen::Isavailable(int i,int k) { int j; j=1; while(j

Dim int1 As Integer Private Sub cmd_click() List1.Clear int1 = 0 Dim i As Single, j As Single i = 1 j = 1 Dim p As Integer, b As Boolean Dim a(1 To 8, 1 To 8) As Boolean Dim ii(1 To 8) As Single Dim jj(1 To 8) As Single a(i, j) = True ii(1) = i jj(1) = j Do Do While i < 8 i = i + 1 If i = 0 Then Exit Sub j = 1 If b = True Then a(i, jj(i)) = False b = False j = jj(i) + 1 End If Do If j > 8 Then i = i - 2: b = True: Exit Do For p = 1 To i - 1 If j = jj(p) Or Abs(i - ii(p)) = Abs(j - jj(p)) Then Exit For Next If p = i Then Exit Do j = j + 1 Loop If b = False Then ii(i) = i: jj(i) = j a(i, j) = True End If Loop

Dim p1 As Integer, p2 As Integer, str1 As String For p1 = 1 To 8 str1 = "" For p2 = 1 To 8 If a(p1, p2) = False Then str1 = str1 & "+ " Else: str1 = str1 & "@ " End If Next List1.AddItem str1 Next int1 = int1 + 1 Caption = int1 i = i - 1: b = True List1.AddItem " " & Str(int1) List1.AddItem vbCrLf Loop End Sub 窗体上一个list控件list1 一个按钮 cmd

回溯算法与八皇后问题(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

N后问题算法 一、实验目的及要求 所要涉及或掌握的知识: 1. 了解皇后相互攻击的条件:如果任意两个皇后在同一行,同一列或同一对角线,则她们相互攻击。 2. 运用迭代的方法实现6皇后问题,求解得到皇后不相互攻击的一个解 3. 在运用迭代的方法实现编程时,要注意回溯点 二、问题描述及实验内容 对6皇后问题求解,用数组c[1…6]来存皇后的位置。c[i]=j表示第i个皇后放在第j列。 最后程序运行的结果是c[1…6]={1,5,8,6,3,7 } 三、问题分析和算法描述 6-QUEENS的算法表示: 输入:空。 输出:对应于6皇后问题的解的向量c[1…6]={1,5,8,6,3,7} 1. for k=1 to 6 2. c[k]=0 //没有放皇后 3. end for 4. flag=false 5. k=1 6. while k>=1 7.while c[k]<=5 8.c[k]=c[k]+1

9.if c为合法着色 then set flag=ture 且从两个while循环退出 10.else if c是部分解 then k=k+1 11.end while 12. c[k]=0 //回溯并c[k]=0 13. k=k-1 14. end while 15. if flag then output c 16. else output “no solution” 四、具体实现 # include #include #include #include #include "iostream" using namespace std; int total = 0; //方案计数 void backtrace(int queen[],int N) { int i, j, k; cout<<"★为皇后放置位置\n"; for (i=1;;) { //首先安放第1行 if(queen[i]

回溯法解八皇后问题 在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");

实验项目: 八皇后问题 1.实验目的: 通过求解皇后问题,熟悉深度优先搜索法DFS(回溯法(Backtracking Algorithms)技术。 2.实验内容: 由n2 个方块排成n行n列的正方形称为n元棋盘。如果两个皇后位于n元棋盘上的同一行、同一列或同一对角线上,则称它们在互相攻击。现要找出使棋盘上n个皇后互不攻击的布局。编制程序解决上述问题,以n=6运行程序,输出结果。 3.程序简介: 将n个皇后放到一个n*n的方阵中,要求每个皇后不在同一行同一列及同一对角线,我的程序是先把每个皇后放在了第零列,然后再按行检查,不符合要求继续下一列,若已经到这一行的最后一列,还没找到符合要求的位置,则回到上一行。 4.算法设计介绍: 定义一个一维数组,数组的下标是皇后所在位置的行数,数组存的值是皇后所在位置的列数,现将A[0]-A[n-1]都赋成零,然后随着检查的进行,皇后的位置也在不断地变化,最后找到一个符合要求的方阵时,本质上就是一个存放整数的一维数组,数组的下标是行数,存放的值是列数。 5.困难及解答 我很久以前就听说过八皇后问题,没想到现在轮到自己编了,一开始还真是特别糊涂呢,后来老师上课把算法大概讲了一遍,就清楚很多了,要说问题,就是一开始纠结怎么存放皇后,我开始想用二维数组着,后来老师说用一

维数组比较好做,我看了一下老师的算法,就明白了大概,经过一段时间就编出来了 5.心得 我编程变得还是很少,天天下决心说以后多编,也没践行,心想着吧,不挂在嘴上了,努力! 6.程序清单 /* //我真诚地保证: //我独立完成了整个程序从分析、设计到编码的所有工作。 //如果在上述过程中,我遇到了什么困难而求教于人,那么,我将在程序实习报告中 //详细地列举我所遇到的问题,以及别人给我的提示。 //我的程序里中凡是引用到其他程序或文档之处, //例如教材、课堂笔记、网上的源代码以及其他参考书上的代码段, //我都已经在程序的注释里很清楚地注明了引用的出处。 //我从未没抄袭过别人的程序,也没有盗用别人的程序,//不管是修改式的抄袭还是原封不动的抄袭。//我编写这个程序,从来没有想过要去破坏或妨碍其他计算机系统的正常运转 文件名称: 创建者: 创建时间: 2011.4.14

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)%调用放置方法

八皇后问题(回溯法)2009-08-11 12:03问题描述: 求出在一个n×n的棋盘上,放置n个不能互相捕捉的国际象棋“皇后”的所有布局,这是来源于国际象棋的一个问题。皇后可以沿着纵横和两条斜线4个方向互相捕捉。 解题思路: 总体思想为回溯法。 求解过程从空配置开始。在第1列~的m列为合理配置的基础上,再配置第m+1列,直至第n列也是合理时,就找到了一个解。在每列上,顺次从第一行到第n行配置,当第n行也找不到一个合理的配置时,就要回溯,去改变前一列的配置。 为使在检查皇后配置的合理性方面简易方便,引入一下4个工作数组: ?数组col[i],表示在棋盘第i列,col[i]行有一个皇后; ?数组a[],a[k]表示第k行上还没有皇后; ?数组b[],b[k]表示第k列右高左低斜线上没有皇后; ?数组c[],c[k]表示第k列左高右低斜线上没有皇后; 代码: #include #include void queen(int N) { //初始化N+1个元素,第一个元素不使用int col[N+1]; //col[m]=n表示第m列,第n行放置皇后 int a[N+1]; //a[k]=1表示第k行没有皇后 int b[2*N+1]; //b[k]=1表示第k条主对角线上没有皇后 int c[2*N+1]; //c[k]=1表示第k条次对角线上没有皇后 int j,m=1,good=1;char awn; for(j=0;j<=N;j++) {a[j]=1;} for(j=0;j<=2*N;j++) {b[j]=c[j]=1;} col[1]=1;col[0]=0; do { if(good) { if(m==N) //已经找到一个解

八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。计算机发明后,有多种方法可以解决此问题。 请编程实现八皇后问题,并把92种解的前三种解输出到屏幕(8*8的二维矩阵,Q代表皇后,X代表空)。并把此问题的求解过程延伸到N皇后问题。 程序代码如下所示: package算法; publicclass EightQueen{ private int index=1; privatefinalstatic int SCALE=8; private int[]answer=new int[SCALE]; private void initArray(){ for(int i=0;i

private boolean canStay(int row,int col){ for(int i=0;i

回溯法(8皇后问题) 1.1算法原理 回溯算法实际是一个类似枚举的搜索尝试方法,其基本思想是在搜索尝试中找问题的解,采用了一种“走不通就掉头”的思想,作为其控制结构。 从一条路往前走,能进则进,不能进则退回来,换一条路再试。八皇后问题就是回溯算法的典型,第一步按照顺序放一个皇后,然后第二步符合要求放第2个皇后,如果没有符合条件的位置符合要求,那么就要改变第一个皇后的位置,重新放第2个皇后的位置,直到找到符合条件的位置就可以了。回溯在迷宫搜索中使用很常见,就是这条路走不通,然后返回前一个路口,继续下一条路。回溯算法说白了就是穷举法。不过回溯算法使用剪枝函数,剪去一些不可能到达最终状态(即答案状态)的节点,从而减少状态空间树节点的生成。回溯法是一个既带有系统性又带有跳跃性的的搜索算法。它在包含问题的所有解的解空间树中,按照深度优先的策略,从根结点出发搜索解空间树。算法搜索至解空间树的任一结点时,总是先判断该结点是否肯定不包含问题的解。如果肯定不包含,则跳过对以该结点为根的子树的系统搜索,逐层向其祖先结点回溯。否则,进入该子树,继续按深度优先的策略进行搜索。回溯法在用来求问题的所有解时,要回溯到根,且根结点的所有子树都已被搜索遍才结束。而回溯法在用来求问题的任一解时,只要搜索到问题的一个解就可以结束。 用回溯法搜索解空间树时,通常采用两种策略来避免无效搜索,提高回溯法的搜索效率。其一是用约束函数在扩展结点处剪去不满足约束的子树;其二是用限界函数剪去不能得到最优 解的子树。 1.2算法适用性 它适用于解一些组合数较大的问题,有条件限制的枚举,即优化的枚举. 1.3算法描述 8皇后回溯算法 1.设Column[8]数组依次存储第一行到第八行的列位置,QUEEN_NUM=8,皇后个数 2.从第一行第一列开始放置,开始放置下一行的皇后(当且仅当前行的皇后位置正确时) 3.判断放置位置是否合理:Column[i]==Column[n],判断是否在同一列, abs(Column[i]-Column[n])==(n-i)),判断时候在斜线上。如果不在用一列,同一斜线上,则位置合理,进行下一行皇后放置,否则回溯 4.当最后一行皇后放置正确时,一种放置方法结束,进行下一种方法,查找。

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

目录 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

八皇后问题 八皇后问题是一个古老而著名的问题,是回溯算法的典型例题。该问题是十九世纪著名的数学家高斯1850年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。 对于八皇后问题的实现,如果结合动态的图形演示,则可以使算法的描述更形象、更生动,使教学能产生良好的效果。下面是用Turbo C实现的八皇后问题的图形程序,能够演示全部的92组解。八皇后问题动态图形的实现,主要应解决以下两个问题。 (1)回溯算法的实现 (a)为解决这个问题,我们把棋盘的横坐标定为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)的对角线(右上至左下)有皇后 (b)为第i个皇后选择位置的算法如下: for(j=1;j<=8;j++) /*第i个皇后在第j行*/ if ((i,j)位置为空))/*即相应的三个数组的对应元素值为1*/ {占用位置(i,j)/*置相应的三个数组对应的元素值为0*/ if i<8 为i+1个皇后选择合适的位置; else 输出一个解 } (2)图形存取 在Turbo C语言中,图形的存取可用如下标准函数实现: size=imagesize(x1,y1,x2,y2) ;返回存储区域所需字节数。

回溯算法 搜索与回溯是计算机解题中常用的算法,很多问题无法根据某种确定的计算法则来求解,可以利用搜索与回溯的技术求解。回溯是搜索算法中的一种控制策略。它的基本思想是:为了求得问题的解,先选择某一种可能情况向前探索,在探索过程中,一旦发现原来的选择是错误的,就退回一步重新选择,继续向前探索,如此反复进行,直至得到解或证明无解。如迷宫问题:进入迷宫后,先随意选择一个前进方向,一步步向前试探前进,如果碰到死胡同,说明前进方向已无路可走,这时,首先看其它方向是否还有路可走,如果有路可走,则沿该方向再向前试探;如果已无路可走,则返回一步,再看其它方向是否还有路可走;如果有路可走,则沿该方向再向前试探。按此原则不断搜索回溯再搜索,直到找到新的出路或从原路返回入口处无解为止。 递归回溯法算法框架[一] procedure Try(k:integer); begin for i:=1 to 算符种数 Do if 满足条件 then begin 保存结果 if 到目的地 then 输出解 else Try(k+1); 恢复:保存结果之前的状态{回溯一步} end; end; 递归回溯法算法框架[二] procedure Try(k:integer); begin if 到目的地 then 输出解 else for i:=1 to 算符种数 Do if 满足条件 then begin 保存结果 Try(k+1); end; end;

例 1:素数环:把从1到20这20个数摆成一个环,要求相邻的两个数的和是一个素数。【算法分析】非常明显,这是一道回溯的题目。从1 开始,每个空位有 20(19)种可能,只要填进去的数合法:与前面的数不相同;与左边相邻的数的和是一个素数。第 20个数还要判断和第1个数的和是否素数。 〖算法流程〗1、数据初始化; 2、递归填数: 判断第J种可能是否合法; A、如果合法:填数;判断是否到达目标(20个已填完):是,打印结果;不是,递归填下一个; B、如果不合法:选择下一种可能; 【参考程序】 program z74;框架[一] var a:array[0..20]of byte; b:array[0..20]of boolean; total:integer; function pd(x,y:byte):boolean; var k,i:byte; begin k:=2; i:=x+y; pd:=false; while (k<=trunc(sqrt(i)))and(i mod k<>0) do inc(k); if k>trunc(sqrt(i)) then pd:=true; end; procedure print; var j:byte; begin inc(total);write('<',total,'>:'); for j:=1 to 20 do write(a[j],' '); writeln; end; procedure try(t:byte); var i:byte; begin for i:=1 to 20 do if pd(a[t-1],i)and b[i] then begin a[t]:=i; b[i]:=false; if t=20 then begin if pd(a[20],a[1]) then print;end

相关文档
最新文档