八皇后问题的解决方案

合集下载

八皇后解题思路

八皇后解题思路

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列上找到了安全位置,则棋局成功。

八皇后问题详细的解法

八皇后问题详细的解法

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

八皇后问题

八皇后问题

八皇后问题八皇后问题是一个古老而著名的问题,是回溯算法的典型例题。

该问题是十九世纪著名的数学家高斯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) ;返回存储区域所需字节数。

八皇后问题

八皇后问题

八皇后问题编辑八皇后问题,是一个古老而著名的问题,是回溯算法的典型例题。

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

高斯认为有76种方案。

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

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

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

之后陆续有数学家对其进行研究,其中包括高斯和康托,并且将其推广为更一般的n皇后摆放问题。

八皇后问题的第一个解是在1850年由弗朗兹·诺克给出的。

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

1874年,S.冈德尔提出了一个通过行列式来求解的方法,这个方法后来又被J.W.L.格莱舍加以改进。

艾兹格·迪杰斯特拉在1972年用这个问题为例来说明他所谓结构性编程的能力。

八皇后问题在1990年代初期的著名电子游戏第七访客和NDS平台的著名电子游戏雷顿教授与不可思议的小镇中都有出现。

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

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

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

C 语言1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 intn=8;intx[9];intnum = 0;//解的个数//判断第k 个皇后能否放在第x[k]列boolPlace(intk){inti = 1;while ( i < k){if ( x[i]==x[k] || (abs (x[i]-x[k]) ==abs (i-k)) )returnfalse ;i++;}returntrue ;}void nQueens(intn){x[0] = x[1] =0;intk=1;while (k > 0){x[k]+=1;//转到下一行while (x[k]<=n && Place(k)==false ){//如果无解,最后一个皇后就会安排到格子外面去 x[k]+=1;}if (x[k]<=n){//第k 个皇后仍被放置在格子内,有解if (k==n){num++;cout << num <<":\t";for (inti=1; i<=n; i++){28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 cout << x[i] <<"\t";}cout << endl;}else {k++;x[k]=0;//转到下一行}}else //第k 个皇后已经被放置到格子外了,没解,回溯k--;//回溯}}int_tmain(intargc, _TCHAR* argv[]){nQueens(n);getchar ();return 0;}Java 算法1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 publicclass Queen {// 同栏是否有皇后,1表示有privateint [] column;// 右上至左下是否有皇后privateint [] rup;// 左上至右下是否有皇后privateint [] lup;// 解答privateint [] queen;// 解答编号privateint num;public Queen() {column =newint [8+1];rup =newint [2*8+1];lup =newint [2*8+1];for (int i =1; i <=8; i++)column[i] =1;2223242526272829303132333435363738394041424344454647484950515253545556575859606162636465 for(int i =1; i <=2*8; i++)rup[i] = lup[i] =1;queen =newint[8+1];}publicvoid backtrack(int i) {if(i >8) {showAnswer();}else{for(int j =1; j <=8; j++) {if(column[j] ==1&&rup[i+j] ==1&&lup[i-j+8] ==1) {queen[i] = j;// 设定为占用column[j] = rup[i+j] = lup[i-j+8] =0; backtrack(i+1);column[j] = rup[i+j] = lup[i-j+8] =1; }}}}protectedvoid showAnswer() {num++;System.out.println("\n解答 "+ num);for(int y =1; y <=8; y++) {for(int x =1; x <=8; x++) {if(queen[y] == x) {System.out.print(" Q");}else{System.out.print(" .");}}System.out.println();}}publicstaticvoid main(String[] args) {Queen queen =new Queen();queen.backtrack(1);66 67 }}Erlang 算法-module(queen).-export([printf/0,attack_range/2]).-define(MaxQueen, 4).%寻找字符串所有可能的排列%perms([]) ->%[[]];%perms(L) ->% [[H | T] || H <- L, T <-perms(L -- [H])].perms([]) ->[[]];perms(L)->[[H | T] || H <- L, T <- perms(L -- [H]),attack_range(H,T) == []].printf() ->L =lists:seq(1, ?MaxQueen),io:format("~p~n",[?MaxQueen]),perms(L).%检测出第一行的数字攻击到之后各行哪些数字%left 向下行的左侧检测%right 向下行的右侧检测attack_range(Queen,List) ->attack_range(Queen,left, List) ++ attack_range(Queen,right, List).attack_range(_, _, [])->[];attack_range(Queen, left, [H | _]) whenQueen - 1 =:= H ->[H];attack_range(Queen,right, [H | _]) when Queen + 1 =:= H->[H];attack_range(Queen, left, [_ | T])->attack_range(Queen - 1, left,T);attack_range(Queen, right, [_ | T])->attack_range(Queen + 1, right, T).C 语言算法C 代码头文件1 2 3 4 5 6 7 8 9 10 11 //eigqueprob.h#include#define N 8 /* N 表示皇后的个数 *//* 用来定义答案的结构体*/typedefstruct {intline;/* 答案的行号 */introw;/* 答案的列号 */}ANSWER_TYPE;/* 用来定义某个位置是否被占用 */12 13 14 15 16 17 18 19 20 typedefenum {notoccued = 0,/* 没被占用 */occued = 1/* 被占用 */}IFOCCUED; /* 该列是否已经有其他皇后占用 */IFOCCUED rowoccu[N];/* 左上-右下对角位置已经有其他皇后占用 */IFOCCUED LeftTop_RightDown[2*N-1];/* 右上-左下对角位置已经有其他皇后占用*/IFOCCUED RightTop_LefttDown[2*N-1];/* 最后的答案记录 */ANSWER_TYPE answer[N];主程序1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 #include "eigqueprob.h"/* 寻找下一行占用的位置 */void nextline(intLineIndex){static asnnum = 0;/* 统计答案的个数 */intRowIndex = 0;/* 列索引 */intPrintIndex = 0;/* 按列开始遍历 */for (RowIndex=0;RowIndex{/* 如果列和两个对角线上都没有被占用的话,则占用该位置 */if ((notoccued == rowoccu[RowIndex])\&&(notoccued == LeftTop_RightDown[LineIndex-RowIndex+N-1])\&&(notoccued == RightTop_LefttDown[LineIndex+RowIndex])){/* 标记已占用 */rowoccu[RowIndex] = occued;LeftTop_RightDown[LineIndex-RowIndex+N-1] = occued;RightTop_LefttDown[LineIndex+RowIndex] = occued;/* 标记被占用的行、列号 */answer[LineIndex].line = LineIndex;answer[LineIndex].row = RowIndex;/* 如果不是最后一行,继续找下一行可以占用的位置 */if ((N-1) > LineIndex ){nextline(LineIndex+1);}/* 如果已经到了最后一行,输出结果 */else{asnnum++;printf ("\nThe %dth answer is :",asnnum);for (PrintIndex=0;PrintIndex{343536373839404142434445464748495051525354 printf("(%d,%d) ",answer[PrintIndex].line+1,answer[PrintIndex].row+1}/* 每10个答案一组,与其他组隔两行 */if((asnnum % 10) == 0)printf("\n\n");}/* 清空占用标志,寻找下一组解 */rowoccu[RowIndex] = notoccued;LeftTop_RightDown[LineIndex-RowIndex+N-1] = notoccued;RightTop_LefttDown[LineIndex+RowIndex] = notoccued;}}}main(){inti = 0;/* 调用求解函数*/nextline(i);/* 保持屏幕结果*/getchar();}C语言实现图形实现对于八皇后问题的实现,如果结合动态的图形演示,则可以使算法的描述更形象、更生动,使教学能产生良好的效果。

算法入门经典-第七章例题7-2八皇后问题

算法入门经典-第七章例题7-2八皇后问题

算法⼊门经典-第七章例题7-2⼋皇后问题原本利⽤回溯思想解决的经典⼋皇后问题,其实也是可以⽤递归解决的~⼋皇后的递归解决思路:从第⼀⾏开始,依次判断0~8列的哪⼀列可以放置Queen,这样就确定了该⾏的Queen的位置,然后⾏数递增,继⽽递归实现下⼀⾏的判断,依次类推直到⾏数增加到8(⾏数从0开始的),此时为递归-----归的条件,即表⽰⼀种⼋皇后的解决⽅法完成,打印结果;之后进⾏下⼀种解决⽅法的寻找,⼤致思路个⼈理解是这样noDanger(row,j,(*chess)[8])函数是判断第row⾏第j列是否可以放置Queen#include<stdio.h>int count=0;//参数row:起始⾏//参数n:表⽰列数//参数(*chess)[8]表⽰指向棋盘每⼀⾏的指针int NotDanger(int row,int j,int (*chess)[8])//⽐较不同⾏同列上是否有其他皇后{int i,k,flag1=0,flag2=0,flag3=0,flag4=0,flag5=0;//判断列⽅向for(i=0;i<8;i++){if(*(*(chess+i)+j)!=0) //在这之前列上有其他皇后{flag1=1;break;}}for(i=row,k=j;i>=0&&k>=0;i--,k--){if(*(*(chess+i)+k)!=0) //左上⽅{flag2=1;break;}}for(i=row,k=j;i<8&&k<8;i++,k++){if(*(*(chess+i)+k)!=0) //右下⽅{flag3=1;break;}}for(i=row,k=j;i>=0&&k<8;i--,k++){if(*(*(chess+i)+k)!=0) //右上⽅{flag4=1;break;}}for(i=row,k=j;i<8&&k>=0;i++,k--){if(*(*(chess+i)+k)!=0) //左下⽅{flag5=1;break;}}if(flag1||flag2||flag3||flag4||flag5){return0;//如果有⼀个位置被占有危险}else return1;} /*int noDanger(int row,int j,int (*chess)[8]){int flag1=0,flag2=0,flag3=0,flag4=0,flag5=0;int i,k;//判断列for(i=0;i<8;i++){if(*(*(chess+i)+j)!=0){flag1=1;break;}}//判断左上⽅for(i=row,k=j;i>=0&&k>=0;i--,k--){if(*(*(chess+i)+k)!=0){flag2=1;break;}}//判断右下⽅for(i=row,k=j;i<8&&k<8;i++,k++){if(*(*(chess+i)+k)!=0){flag3=1;break;}}//判断左下⽅for(i=row,k=j;i<8&&k>=0;k--,i++){if(*(*(chess+i)+k)!=0){flag4=1;break;}}//判断右上⽅for(i=row,k=j;i>=0&&k<8;k++,i--){if(*(*(chess+i)+k)!=0){flag5=1;break;}}if(flag1||flag2||flag3||flag4||flag5){return 0;}else{return 1;}} */EightQueen(int row,int n,int (*chess)[8]){int chess2[8][8];int i,j;for(i=0;i<8;i++){for(j=0;j<8;j++){chess2[i][j]=chess[i][j];}}if(8==row){printf("第%d 种\n",count+1);for(i=0;i<8;i++){for(j=0;j<8;j++)printf("%3d ",*(*(chess2+i)+j));printf("\n");}count++;}else{//判断这个位置是否危险 j<列for(j=0;j<n;j++){if(NotDanger(row,j,chess2))//尝试每⼀列是否危险 {for(i=0;i<8;i++){//整⾏所有列的位置赋值为0*(*(chess2+row)+i)= 0;}*(*(chess2+row)+j)=1;//皇后的位置赋值为1EightQueen(row+1,n,chess2);//继续往下⼀⾏递归 }}}}int main(){int chess[8][8],i,j;for(i=0;i<8;i++){for(j=0;j<8;j++)chess[i][j]=0;}EightQueen(0,8,chess);printf("总共有%d种解决⽅法",count);return0;}。

C++课程设计八皇后问题

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,关键的类好了,然后编辑好类的成员,然后编辑主函数利用好这些类的成员,让其运算出结果。

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

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

2014年春季学期《C项目设计》报告题目:八皇后问题学号:092213112姓名:刘泽中组名:1指导教师:宋东兴日期:2014.05.15目录正文 (3)1.问题描述 (3)2. 总体设计与分析 (3)3. 相关代码 (5)4. 调试分析 (9)5.软件使用说明书 (11)总结 (11)附录:部分原程序代码 (12)一、问题描述1.八皇后问题:是一个古老而著名的问题。

该问题是十九世纪著名的数学家高斯1850年提出:在8×8棋盘上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法?2.解决八皇后问题的关键在于:(1)找到合理的数据结构存放棋子的摆放位置。

(2)要有合理的冲突检查算法。

采用的方法是,先把8个棋子摆在棋盘上,每行摆一个,然后去检查这种摆放是否有冲突,如果没有冲突,即找到了一种解决方案。

由于皇后的摆放位置不能通过某种公式来确定,因此对于每个皇后的摆放位置都要进行试探和纠正,这就是“回溯”的思想。

在8个皇后未放置完成前,每行摆放一个皇后,摆放第i个皇后和第i+1个皇后的试探方法是相同的,因此完全可以采用递归的方法来处理。

二、总体设计与分析1.设计效果画一个8*8的国际象棋盘,在棋盘某一位置上放一棋子,并让它按从左到右的方向自动运动,用户可以使用光标键调整棋子运动的方向,找出所有可能的摆放方案,将包含指定的棋子的(如3行4列)摆放方案找出并显示出来。

2.、总体设计程序总体分为两大块:(1)八皇后摆法的寻找;(2)棋盘及棋子的设计。

3、详细模块(1)八皇后摆法的寻找:int chess[8][8]={0}; //二维数组表示8*8棋盘,全部清0,(0代表该位没有放棋子)void queen(int i,int n){ //i表示从第i行起为后续棋子选择合适位置,n代表n*n棋盘if(i==n)output(n); //输出棋盘当前布局;else{for(j=0;j<n;j++){ //每行可能有n个摆放位置chess[i][j] = 1; //在第i行,j列上放一棋子if(!canAttack(i,j)) //如果当前布局合法,不受前i-1行的攻击queen(i+1,n); //递归摆放i+1行chess[i][j] = 0; //移走第i行,j列的棋子}}}int canAttack(int i,int j){ //判断0到i-1行已摆放的棋子,对[i,j]位置是否可以攻击for(m=0;m<i;m++){for(n=0;n<8;n++){if(chess[m][n]==1){if(m==i||n==j) return 1;if(m+n==i+j || m-n==i-j) return 1;}}}return 0;}void output(){ //输出一组解,即打印出8个皇后的坐标for(int i=0;i<8;i++){for(int j=0;j<8;j++){if(chess[i][j]==1){printf("(%d,%d)",i,j);}}}printf(“\n”);}int main(){queen(0,8);return 0;}(2)棋盘及棋子的设计:void drawBlock(int i,int j){ //棋盘的设计(每一个小方块)int x0,y0,x1,y1;x0=ORGX+j*W;y0=ORGY+i*H;x1=x0+W-1;y1=y0+H-1;setcolor(WHITE);rectangle(x0,y0,x1,y1);setfillstyle(1,LIGHTGRAY);floodfill(x0+1,y0+1,WHITE);setcolor(WHITE);line(x0,y0,x1,y0);line(x0,y0,x0,y1);setcolor(BLACK);line(x1,y0,x1,y1);line(x0,y1,x1,y1);}void drawBall(Ball ball){ //棋子的设计int x0,y0;x0=ball.startX+ball.c*ball.w+ball.w/2;y0=ball.startY+ball.r*ball.h+ball.h/2;setcolor(RED);setfillstyle(1,RED);fillellipse(x0,y0,10,10);}4.程序设计思路:先设计程序,找到八皇后的摆放位置,方法是:先把8个棋子摆在棋盘上,每行摆一个,然后去检查这种摆放是否有冲突,如果没有冲突,即找到了一种解决方案。

八皇后以及N皇后问题分析

八皇后以及N皇后问题分析

⼋皇后以及N皇后问题分析⼋皇后是⼀个经典问题,在8*8的棋盘上放置8个皇后,每⼀⾏不能互相攻击。

因此拓展出 N皇后问题。

下⾯慢慢了解解决这些问题的⽅法:回溯法:回溯算法也叫试探法,它是⼀种系统地搜索问题的解的⽅法。

回溯算法的基本思想是:从⼀条路往前⾛,能进则进,不能进则退回来,换⼀条路再试。

在现实中,有很多问题往往需要我们把其所有可能穷举出来,然后从中找出满⾜某种要求的可能或最优的情况,从⽽得到整个问题的解。

回溯算法就是解决这种问题的“通⽤算法”,有“万能算法”之称。

N皇后问题在N增⼤时就是这样⼀个解空间很⼤的问题,所以⽐较适合⽤这种⽅法求解。

这也是N皇后问题的传统解法,很经典。

算法描述:1. 算法开始,清空棋盘。

当前⾏设为第⼀⾏,当前列设为第⼀列。

2. 在当前⾏,当前列的判断放置皇后是否安全,若不安全,则跳到第四步。

3. 在当前位置上满⾜条件的情况: 在当前位置放⼀个皇后,若当前⾏是最后⼀⾏,记录⼀个解; 若当前⾏不是最后⼀⾏,当前⾏设为下⼀⾏,当前列设为当前⾏的第⼀个待测位置; 若当前⾏是最后⼀⾏,当前列不是最后⼀列,当前列设为下⼀列; 若当前⾏是最后⼀⾏,当前列是最后⼀列,回溯,即清空当前⾏以及以下各⾏的棋盘,然后当前⾏设为上⼀⾏,当前列设为当前⾏的下⼀个待测位置; 以上返回第⼆步。

4.在当前位置上不满⾜条件: 若当前列不是最后⼀列,当前列设为下⼀列,返回到第⼆步; 若当前列是最后⼀列,回溯,即,若当前⾏已经是第⼀⾏了,算法退出,否则,清空当前⾏以及以下各⾏的棋盘,然后,当前⾏设为上⼀⾏,当前列设为当前⾏的下⼀个待测位置,返回第⼆步。

如何判断是否安全:把棋盘存储为⼀个N维数组a[N],数组中第i个元素的值代表第i⾏的皇后位置,这样便可以把问题的空间规模压缩为⼀维O(N),在判断是否冲突时也很简单, ⾸先每⾏只有⼀个皇后,且在数组中只占据⼀个元素的位置,⾏冲突就不存在了, 其次是列冲突,判断⼀下是否有a[i]与当前要放置皇后的列j相等即可。

八皇后问题及其扩展解法

八皇后问题及其扩展解法

C++实现八皇后问题及其扩展N皇后问题(经典回溯算法)八皇后问题是一个古老而著名的问题,是回溯算法的典型例题。

该问题是十九世纪著名的数学家高斯1850年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。

高斯认为有76种方案。

1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用八皇后问题是一个古老而著名的问题,是回溯算法的典型例题。

该问题是十九世纪著名的数学家高斯1850年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。

高斯认为有76种方案。

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

事实上就是有92种解法。

了解了基本的原理后,我们开始分析:1.我们需要一个数据存放已经放置皇后的位置,用指针表示的一维数据*position,长度为N(N为放置的皇后总数),可能有人会问为什么不用二维数组,用下票i,j准备定位,事实是这样的,因为该问题是每行,每列,每组对角线只可能出现一个皇后,所以用一维数据position+i中的i则能代码第几行,而值*(position+i)则表示该行中的列值,其实质与二维数组无异.2.判断每行可放置皇后,假设要判断第n行,则从position中从0到n-1每一个已放皇后的位置判断(列,对角线)具体算法如下:#include <iostream>#include <math.h>#include <malloc.h>using namespace std;int *position; //放置的位置int queen; //皇后数目int count; //第N种可能性//判断第n行是否放置皇后bool SignPoint(int n){for (int i=0;i<n;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<queen;i++){for (int j=0;j<queen;j++){if (j == position[i]){printf("* ");}else{printf("0 ");}}printf("\n");}printf("\n");return;}else{for (int i=0;i<queen;i++){position[n] = i;if(SignPoint(n))//如果该位置放置皇后正确的话,则到下一行{SetQueen(n+1);}}}}int main(int argc, char * argv[]){cout<<"请输入皇后的总数:"<<endl;cin>>queen;position = (int*)malloc(sizeof(int));SetQueen();cout<<"摆放完毕"<<endl;cin.get();cin.get();return 0;}。

八皇后问题实验报告

八皇后问题实验报告

实验报告——八皇后问题求解(递归和非递归)学号:专业年级:姓名:一、需求分析(要实现的功能描述)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语言编程问题掌握的并非十分熟练,因而在程序的调试过程中出现了一些问题。

4八皇后问题

4八皇后问题

实验四八皇后问题
一、目的和要求
1. 掌握递归的使用方法。

2. 掌握回溯法。

二、实验内容
八皇后问题是十九世纪著名的数学家高斯提出的:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻(任意两个皇后都不能处于同一行、同一列或同一斜线上),问有多少种摆法?输出所有的皇后摆法。

三、算法:
提示:
1.皇后q1(x1,y1)和皇后q2(x2,y2)相互吃掉的条件:
x1 == x2 || y1 == y2 || x1 – x2 == y1 – y2 || x1 – x2 == y2 – y1
2.用回溯法解决八皇后问题的步骤为:
用一个数组存储当前成功摆放的皇后位置,以便下一列摆放皇后时进行安全判断。

因为一列(行)只能摆放一个皇后,否则会互相吃掉,所以可以用列(行)号来作为递归函数的n
1)从第1列开始,为皇后找到安全位置,然后递归进行下一列。

2) 如果在第8列上找到了安全位置,则棋局成功,输出此种摆放下所有皇后的位置信息。

3) 如果在第n列出现死胡同(在所有位置都不能安全摆放皇后了),则后退到上一列进行回溯(如果用递归实现,该回溯是递归调用自动完成)。

程序请自行设计。

皇后问题详细的解法

皇后问题详细的解法

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++)print(a[i]);
}
10
}
1 回溯法
有“通用的解题法”之称。 回溯法的基本做法是搜索,或是一种组织得井井有条
枚举得有个顺序,否则 轻则有漏的、重复的; 重则无法循环表示。
6
1.按什么顺序去查找所有的解 a.盲目的枚举算法
void main() {
int x[100]; for (x[1]=1;x[1]<=10;x[1]++) for (x[2]=1;x[2]<=10;x[2]++)
for (x[3]=1;x[3]<=10;x[3]++) for (x[4]=1;x[4]<=10;x[4]++) for (x[5]=1;x[5]<=10;x[5]++) for (x[6]=1;x[6]<=10;x[6]++) for (x[7]=1;x[7]<=10;x[7]++) for (x[8]=1;x[8]<=10;x[8]++) if (check(x)==0) { printf(x); }
}
该如何解决冲突的问题呢?
1.行;我们是按照行枚举的,保证了一行一个皇后; 2.列:判断是否存在x[i]=x[j] 3.对角线:主对角线的i-j与从对角线的i+j存在特殊关系,如 图:

八皇后问题(N皇后问题)

八皇后问题(N皇后问题)

⼋皇后问题(N皇后问题)⼋皇后问题,是⼀个古⽼⽽著名的问题,是回溯算法的典型案例。

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

⾸先来看看这张模拟⼋皇后的图。

这张图说明皇后具有横轴、竖轴以及两个斜轴⽅向的杀伤⼒,也就是像⽶字形⼀样;为了减少判断,我们按照⼀个⽅向往另⼀个⽅向排列,中间不能跳⾏,这样我们就可以只判断已经有皇后的位置,还没有皇后的就可以偷懒不⽤判断了。

我的⽅案是:1.从最下⾯开始排列,然后往上添加,从左往右排列,这样就只需要判断⽐⾃⼰Y坐标低的具有杀伤能⼒的位置有没有皇后就OK ⽅法是把⾃⼰假定要放置皇后的位置的X和Y轴都依据判断特性进⾏处理;例如,左斜线X和Y轴都减1;中间的只需要把Y 轴减1;右边的和左边的相反,X轴加1,Y轴减1;注意处理边界问题。

2.为了找到合适的位置我们需要在查找失败的时候具备回溯的能⼒,就需要退回到前⼀⾏(Y=Y-1,注意XY是否到边界),直⾄能回溯或者全部判断完毕,每次回溯的时候记得X轴要从头开始 3.通过⼀个数据结构记录正在查找的⽅案,通过另⼀个数据结构记录已经找到的⽅案,当然也可以⽤⼀个变量记录⽅案个数下⾯这张⿊⾊背景是其中⼀个⽅案的截图,第⼀⾏代表皇后的坐标xy;后⾯的是棋盘,这⾥输出竖轴是x,横轴是y,从上到下,从左到右,其中*是边界,空格是空区,#是皇后。

#include <iostream>#include <cstring>#include "DTString.h"#include "LinkList.h" // 这⾥使⽤链表存储皇后的位置using namespace std;using namespace DTLib;template <int SIZE> // N皇后问题,SIZE表⽰皇后个数或者棋盘⼤⼩class QueenSolution : public Object{protected:enum { N = SIZE + 2 }; // N表⽰棋盘⼤⼩,为了边界识别,棋盘四周都要加⼀格struct Pos : public Object // ⽅位结构体{Pos(int px = 0, int py = 0) : x(px), y(py) { }int x;int y;};int m_chessboard[N][N]; // 棋盘,0表⽰空位,1表⽰皇后,2表⽰边界Pos m_direction[3]; // 共3个⽅向;⽅向-1、-1表⽰左斜线;0、-1表⽰下⽅;1、-1表⽰右斜线;⾸先从最下⽅开始,所以只需考虑下⾯的⾏。

八皇后问题最简单算法

八皇后问题最简单算法

八皇后问题最简单算法
八皇后问题最简单算法是使用回溯法。

1. 回溯法在求解八皇后问题时,会生成一个8位的二进制数,每一位代表一列是否放置皇后。

如果某一列放置了皇后,则该位为1,否则为0。

2. 在放置皇后时,如果当前位置可以放置皇后,则尝试放置。

如果放置后当前位置形成了一个合法的棋盘,则继续递归地放置下一个皇后。

如果放置后形成了一个不合法的棋盘,则回溯到上一个状态,尝试其他位置。

3. 如果所有8个皇后都放置完毕,且形成了一个合法的棋盘,则找到了一个解。

以上信息仅供参考,如需了解更多信息,建议查阅八皇后问题相关书籍或咨询专业人士。

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

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

八皇后问题(递归+非递归)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;}。

八皇后问题详细的解法课件

八皇后问题详细的解法课件
详细描述
在放置后续的皇后时,我们重复第二步和第三步的操作。我们需要选择一个位置放置新的皇后,然后 检查是否与已放置的皇后冲突。如果冲突,我们重新选择位置,直到找到一个安全的位置。通过重复 这个过程,我们可以逐步填满整个棋盘。
找到所有解的
总结词
当所有皇后都已放置完毕后,输出棋盘上所有皇后的位置,即为问题的解。
八皇后问题详细的解法课 件
• 八皇后问题的定义和背景 • 八皇后问题的基本解法 • 八皇后问题的详细解法 • 八皇后问题的优化解法 • 八皇后问题解法的应用和扩展
01
八皇后问题的定义和背景
问题的起源和历史
1878年,八皇后问题由德国棋手马克斯·贝赤尔提出,是国际象棋中的一种著名问题 。
问题的起源与国际象棋的棋盘和皇后棋子有关,目标是放置八个皇后在棋盘上,使 得没有任何两个皇后在同一行、同一列或同一对角线上。
解。
在递归函数中,我们需要判断 当前位置是否可以放置皇后,
并更新棋盘状态和方向。
如果当前位置放置皇后导致冲 突,我们需要回溯到上一步,
重新尝试其他解。
03
八皇后问题的详细解法
初始化棋盘
总结词
创建一个8x8的棋盘,所有格子都 处于未被占领状态。
详细描述
棋盘是解决八皇后问题的基础, 我们需要一个8x8的空白棋盘,所 有的格子都处于未被占领的状态 ,这是我们放置皇后的起点。
放置第一个皇后
总结词
在棋盘上选择一个位置放置第一个皇 后,并标记该位置为已占领。
详细描述
在棋盘上选择任意一个位置放置第一 个皇后,并将该位置标记为已占领。 这是解决问题的第一步,也是最简单 的一步。
放置第二个皇后并处理冲突
总结词
在棋盘上选择一个位置放置第二个皇后,并检查是否与第一个皇后冲突,如果冲突则调整位置,直至找到一个安 全的位置。

八皇后问题详细的解法

八皇后问题详细的解法
八皇后问题
1
1八皇后问题背景 2盲目的枚举算法 3加约束的枚举算法 4回溯法及基本思想 5 回溯法应用 6八皇后问题的递归回溯算法 7八皇后问题的非递归回溯算法
2
【背景】 八皇后问题是一个以国际象棋为背
景的问题: 如何能够在 8×8 的国际象棋棋盘上
放置八个皇后,使得任何一个皇后都 无法直接吃掉其他的皇后?为了达到 此目的,任两个皇后都不能处于同一 条横行、纵行或斜线上。
}
}
23
20
2 回溯法应用-算法框架-递归算法框架
int a[n]; Queens(int k) { if (k>n) 即表示最后一个皇后摆放完毕,输出结果;
else for(i=下界 ; i<=上界; i++) //枚举K个皇后所有可能的路径 {依次从列顶端开始搜索,一直到列底端,直到找到合适位置,如
果未找到,自动返回上层递归
的,能避免不必要搜索的穷举式搜索法。这种方法适 用于解一些组合数相当大的问题。 回溯法在问题的解空间树中,按深度优先策略,从根 结点出发搜索解空间树。算法搜索至解空间树的任意 一点时,先判断该结点是否包含问题的解。如果肯定 不包含,则跳过对该结点为根的子树的搜索,逐层向 其祖先结点回溯;否则,进入该子树,继续按深度优 先策略搜索。
for(a[8]=1;a[8]<=8;a[8]++) 此算法可读性很好,
{if (check(a,8)==0)continue; 体现了“回溯”。但
else for(i=1;i<=8;i++) 它只能解决八皇后问
print(a[i]); }
题,而不能解决任意
}}}}}}}

1213:八皇后问题

1213:八皇后问题

1213:⼋皇后问题⾸先可以试图去简化问题,将问题转化为为每⼀列确定⼀个有效的⾏号。

因为同⼀列只能有⼀个皇后,并且需要在⼋列中确定⼋个皇后,即每⼀列都必定有且只有⼀个皇后。

经过简化后,显然,通过⼀个⼀维数组即可以确定⼀组有效解。

关于check:不为同⼀⾏或同⼀列的判定⽐较简单(这⾥省略)(i1,j1)与(i2,j2)在同⼀条斜线上的判定:i1-i2==j1-j2 || i1-i2==j2-j1问题经过这样⼀次抽丝剥茧后,剩余的思路⼤致就是深度搜索、临界输出。

特别重复:a[j]表⽰第j列的皇后所在的⾏数1 #include<iostream>2 #include<cstdio>3using namespace std;45const int N=10;6int ans,a[N];7void print(){8 printf("No. %d\n",++ans);9for(int i=1;i<=8;i++){10for(int j=1;j<=8;j++)11if(a[j]==i)printf("1 ");12else printf("0 ");13 printf("\n");14 }15 }16bool check(int x,int d){17for(int i=1;i<d;i++){18if(a[i]==x||x-a[i]==d-i||x-a[i]==i-d)19return0;20 }21return1;22 }23void solve(int d){24if(d==9){25 print();26return;27 }28for(int i=1;i<=8;i++){29if(check(i,d)){30 a[d]=i;31 solve(d+1);32 }33 }34 }35int main(){36 solve(1);37return0;38 }。

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

算法总结
3
解决八皇后问题常用算法
3.1
枚举法解决八皇后问题
3.2
非递归回溯法解决八皇后问题
3.3
递归回溯法解决八皇后问题
3.0
八皇后问题约束条件
a( i ) 1 2 3 4 5 6 7 8 a( 1) 2 0 -1 3 -2 4 -3 5 -4 6 -5 7 -6 8 -7 9
a( 2 ) a( 3 ) a( 4) a( 5 ) a( 6) a( 7 ) a( 8)
9 3 10 2 11 1 12 0 13 -1 14 -2
9 5 10 4 11 3 12 2 13 1 14 0 15 -1
9 7 10 6 11 5 12 4 13 3 14 2 15 1 16 0
3.0
八皇后问题约束条件
a( i ) =j 第i行j列放置皇后
判断不同列 a(i)≠a(j) 判断不同对角线 i-a(i)≠j-a(j) 判断不同反对角线 i+a(i)≠j+a(j)
取下一个………………
取下一个q (1)
用语言编程
For q1 = 1 To 8 For q2 = 1 To 8 For q3 = 1 To 8 For q4 = 1 To 8 For q5 = 1 To 8 For q6 = 1 To 8 For q7 = 1 To 8 For q8 = 1 To 8 q(q1) = q1 : q(q2) = q2 : q(q3) = q3 : q(q4) = q4 q(q5) = q5 : q(q6) = q6 : q(q7) = q7 : q(q8) = q8 If putdown(q)=1 Then printstr(q) Next q8 Next q7 Next q6 Next q5 Next q4 Next q3 Next q2 Next q1
3.3
递归回溯法解决八皇后问题
调用search(1) 行号r=形参
r>8
是 否 否 是
输出解
i<8 q(r)=i q(r)列符合放 置条件
是 否
返回0
i=i+1
调用search(r+1)
Private Function search(ByVal r As Integer) If (r > 8) Then printstr(q) Return 0 End If For i = 1 To 8 q(r) = i Dim OK% = 1 For j = 1 To r - 1 If q(r) = q(j) Or Math.Acos(r - j) = Math.Abs(q(r) - q(j)) Then OK = 0 Exit For End If Next If OK = 1 Then search(r + 1) Next Return 0 End Fun皇后问题
皇后放置行号r=1
行号r>0

否 否
退出
r=r-1 q(r)=0
列q(r)<8

q(r)=q(r)+1
q(r)列符合放 置条件


r≥8


输出解
r=r+1
Dim r = 1 While r > 0 While q(r) < 8 q(r) = qq(r) + 1 Dim OK% = 1 For j = 1 To r - 1 If q(r) = q(j) Or math.abs(r – j) = math.abs( q(r) - q(j)) Then OK = 0 Exit For End If Next If OK = 1 Then If (r < 8) Then r=r+1 Else printstr(q) ‘调用打印输出放置解 End If End If End While qq(r) = 0 r=r-1 End While
=j 第i行j列放置皇后 判断不同列 a(i)≠a(j) 判断不同对角线 i-a(i)≠j-a(j) 判断不同反对角线 i+a(i)≠j+a(j)
3 1 4 2 5 3 6 4 7 5 8 6
4 0 -1 5 -2 6 -3 7 -4 8 -5 9 10 -6 5 1 6 2 7 3 8 4 6 0 -1 7 -2 8 -3 9 10 -4 11 -5 7 1 8 2 8 0 -1 9 10 -2 11 -3 12 -4 9 1 10 0 11 -1 12 -2 13 -3
abs(i-j)≠ abs(a(i)-a(j))
3.1
枚举法解决八皇后问题
思想:利用8重循环,分别描述8个皇后处在各 行的8个状态,再各个状态中依次找出符合约束条 件的皇后状态 。
第一行q (1)所在列分别依次1~8列
第二行q(2)所在列分别依次1~8列 第三行q (3)所在列分别依次1~8列 第四行q (4)所在列分别依次1~8列 第五行q (5)所在列分别依次1~8列 第六行q (6)所在列分别依次1~8列 第七行q (7)所在列分别依次1~8列 第八行q (8)所在列分别依次1~8列 判断q是否符合约束条件,满足就打印 取下一个q (8) 取下一个q(7)
八皇后问题最优解
物电学院 刘东
八皇后问题,是一个古老 而著名的问题,是回溯算法的 典型案例。
内容提要
1
回溯法概述
2
八皇后问题
3
解决八皇后问题常用算法
4
算法分析与总结
1
回溯法概述
2
八皇后问题
在8*8的国际象棋棋盘中放八个皇后,使任意两个 皇后都不能互相吃掉。规则:皇后能吃掉同一行、 同一列、同一对角线的任意棋子。
相关文档
最新文档