八皇后问题vb解
八皇后问题详细的解法

若无法放下皇后则回到上一行, 即回溯
当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语言实现图形实现对于八皇后问题的实现,如果结合动态的图形演示,则可以使算法的描述更形象、更生动,使教学能产生良好的效果。
八皇后问题递归算法

八皇后问题递归算法八皇后问题是一个经典的数学问题,其目标是在一个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;}```我们可以编写一个主函数来调用递归算法并打印结果。
八皇后92种解

八皇后92种解(不排除对称和旋转所得棋局)一.穷举法(1)不用递归(教材P282例12。
3)#include<stdio.h>int data[9],iCount;bool check();void out(void);void main(){int i1,i2,i3,i4,i5,i6,i7,i8;for(i1=1;i1<=8;i1++)for(i2=1;i2<=8;i2++)for(i3=1;i3<=8;i3++)for(i4=1;i4<=8;i4++)for(i5=1;i5<=8;i5++)for(i6=1;i6<=8;i6++)for(i7=1;i7<=8;i7++)for(i8=1;i8<=8;i8++){data[1]=i1;data[2]=i2;data[3]=i3;data[4]=i4;data[5]=i5;data[6]=i6;data[7]=i7;data[8]=i8;if(check())out();}}bool check(){int i,m;for(m=1;m<9;m++)for(i=1;i<m;i++){if(data[m]==data[i])return false;if(data[m]-m==data[i]-i) return false;if(data[m]+m==data[i]+i) return false;}return true;}void out(){int i;printf( "No.%-5d " , ++iCount);for(i = 1 ; i < 9 ; i++)printf( "%d " , data[i]);printf( "\n ");}(2)递归实现(教材p286)#include<stdio.h>int iCount;int data[9];bool check();void out();void queen(int r);void main(){queen(8);}void queen(int r){int i;for(i=1;i<=8;i++){data[8-r+1]=i;if(r>1)queen(r-1);elseif(check())out();}}bool check(){int i,m;for(m=1;m<9;m++)for(i=1;i<m;i++){if(data[m]==data[i])return false;if(data[m]-m==data[i]-i) return false;if(data[m]+m==data[i]+i) return false;}return true;}void out(){int i;printf( "No.%-5d " , ++iCount);for(i = 1 ; i < 9 ; i++)printf( "%d " , data[i]);printf( "\n ");}二.试探法(1)不用递归(教材P283)#include<stdio.h>int iCount;int data[9],m;bool check(int m);void change(void);void extend(void);void out();void main(){data[0]=0;data[1]=1;m=1;while(m>0)if(check(m)){if(m==8){out();change();}elseextend();}elsechange();}void change(void){while(data[m]==8)m=m-1;data[m]=data[m]+1;}void extend(void){m=m+1;data[m]=1;}bool check(int m){int i;for(i=1;i<m;i++){if(data[m]==data[i])return false;if(data[m]-m==data[i]-i) return false;if(data[m]+m==data[i]+i) return false;}return true;}void out(){int i;printf( "No.%-5d " , ++iCount);for(i = 1 ; i < 9 ; i++)printf( "%d " , data[i]);printf( "\n ");}(2)递归实现(教材P287)#include<stdio.h>int iCount;int data[9];bool check(int m);void out();void queen(int r);void main(){queen(8);}void queen(int r){int i;for(i=1;i<=8;i++){data[8-r+1]=i;if(check(8-r+1))if(r>1)queen(r-1);elseout();}}bool check(int m){int i;for(i=1;i<m;i++){if(data[m]==data[i])return false;if(data[m]-m==data[i]-i) return false;if(data[m]+m==data[i]+i) return false;}return true;}void out(){int i;printf( "No.%-5d " , ++iCount);for(i = 1 ; i < 9 ; i++)printf( "%d " , data[i]);printf( "\n ");}。
八皇后问题的解决方案

算法总结
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.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)) //搜
8皇后问题分析与解法

递归算法——八皇后问题1、背景问题描述八皇后问题是一个古老而著名的问题,该问题的目标是在8×8的国际象棋棋盘上放置八个皇后,使得任意两个皇后都不在同一行,或同一列或同一对角线上。
如图1所示就是八皇后问题的一个解。
图1 八皇后问题的一个解1854年在柏林的象棋杂志上不同的作者发表了40种不同的解。
大数学家高斯认为有76种不同的方案。
后来有人用图论的方法算出92种不同的解。
能否利用程序算出所有满足条件的解的数目呢?2、抽象表示及存储对于这种矩形排列的棋盘而言,用二维数组存储棋盘的状况是最容易想到的方法。
可以设置一个8*8的二维数组,令有棋子的位置为1,无棋子的部分为0。
事实上,由于8个皇后中任意两个皇后都不在同一行,因此8个皇后只能各自占据一行。
不妨认为8个皇后编号为0、1、……、7,它们各自占据棋盘的第1行、第2行、……、第8行。
从而可以使用长度为8一维数组表示棋盘状态,数组元素的下标表示棋子所在行,数组元素的值表示各个棋子所在的列。
使用的存储方式不同,其采用的算法已有很大区别。
3、问题分析及算法设计假定用二维数组A存储棋盘的情况,可以考虑下面两种思路。
思路一:不考虑任何限制的穷举法。
用8×8的二维数组存储棋盘,若在(i,j)处有子,则令A[i][j]=1,否则A[i][j]=0。
于是8个棋子第1个有64种摆放方法,第2个有63种放法,……,第8个有57种放法,则所有摆放方法有64×63×62×…×57种。
可以列举每一种摆法,而后考察每种方法是否符合条件。
这个计算量非常大。
思路二:考虑经过优化的穷举法(二维数组方案)。
若8个棋子位于8行8列的棋盘中,要求任意两个不同行、不同列,则任一解必然是各行、各列只包含一个棋子,其它情况必然不是解。
于是可以做个8重循环,把每个皇后安排在每行的每个位置都试一遍。
算法如下:将整个棋盘数组赋值为0;for(1号皇后从1行1列到1行8列){将1号皇后能控制的线路(横向、竖线、斜线)全部设为1;for(2号皇后从2行1列到2行8列){if(2号皇后控制的线路全部为0){将2号皇后能控制的线路(横向、竖线、斜线)全部设为2;for(3号皇后从3行1列到3行8列){if(3号皇后控制的线路全部为0){将3号皇后能控制的线路全部设为3;……for(8号皇后从8行1列到8行8列){if(8号皇后控制的线路全部为0){将8号皇后能控制的线路全部设为8;记录该棋盘为一个解;}将8号皇后控制的线路全部恢复为0;}……}将3号皇后控制的线路全部恢复为0;}}将2号皇后控制的线路全部恢复为0;}将1号皇后控制的线路全部恢复为0}上述算法中的多重循环虽易于理解,但程序嵌套结构较为复杂,形式死板,不易扩展。