八皇后问题分析及解决(C语言)

内容:

       八皇后问题是一个古老而著名的问题,是回溯算法的典型例题。该问题是19世纪著名的数学家高斯于1850年提出的:在8*8格的国际象棋棋盘上,安放八个皇后,要求没有一个皇后能够“吃掉”任何其他一个皇后,即任意两个皇后都不能处于同一行、同一列或者同一条对角线上,这样的格局称为问题的一个解。写一个程序求出所有解。

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

步骤:

1.算法分析:

       八皇后在棋盘上的分布的各种可能的格局数目非常大,约等于2^32种,但是,可以将一些明显不满足问题要求的格局排除掉。由于任意两个皇后不能同行,即每一行只能放置一个皇后,因此将第i个皇后放置在第i行上。这样在放置第i个皇后时,只要考虑它与前i-1个皇后处于不同列和不同对角线位置上即可。

       对于八皇后的求解可采用回溯算法,从上至下依次在每一行放置皇后,而进行搜索,若在某一行的任意一列放置皇后均不能满足要求,则不能向下搜索,而进行回溯。回溯至有其他列可放置皇后的一行,再向下搜索,直到搜索至最后一行,找到可行解,输出结果。

解决思路:

①从棋盘的第一行开始,从第一个位置开始,依次判断当前位置是否能够放置皇后,判断的依据为:同该行之前的所有行中皇后的所在位置进行比较,如果在同一列,或者在同一条斜线上(斜线有两条,为正方形的两个对角线),都不符合要求,继续检验后序的位置。

②如果该行所有位置都不符合要求,则回溯到前一行,改变皇后的位置,继续试探。

③如果试探到最后一行,所有皇后摆放完毕,则直接打印出 8*8 的棋盘。最后一定要记得将棋盘恢复原样,避免影响下一次摆放。

2.概要设计:

函数 作用
Check() 用来判断皇后所放位置(row,column)是否可行
Otput() 用来输出可行解,即输出棋盘
EightQueen() 采用递归算法实现在row行放置皇后

3.程序流程图:

 4.源程序(编译环境vc++6.0):

#include<stdio.h>
#include<stdlib.h>
typedef int BOOL;
#define true 1
#define false 0
int num=0;  //解数目
char m[8][8]={'*'};//m[8][8]表示棋盘,初始为*,表示未放置皇后
//对于棋盘前row-1行已放置好皇后
//检查在第row行、第column列放置一枚皇后是否可行
BOOL Check(int row,int column)
{
	int i,j;
	if(row==1)return true;
	for(i=0;i<=row-2;i++)//纵向只能有一枚皇后
	{
		if(m[i][column-1]=='Q')return false;
	}
	//左上至右下只能有一枚皇后
	i=row-2;
	j=i-(row-column);
	while(i>=0&&j>=0)
	{
		if(m[i][j]=='Q')return false;
		i--;
		j--;
	 } 
	 //右上至左下只能有一枚皇后
	 i=row-2;
	 j=row+column-i-2;
	 while(i>=0&&j<=7)
	 {
	 	if(m[i][j]=='Q')return false;
		i--;
		j++;
	  } 
	  return true;
}
void Output()  //当已放置8枚皇后,为可行解时,输出棋盘
{
	int i,j;
	num ++;
	printf("可行解  %d:\n",num);
	for(i=0;i<8;i++)
	{
		for(j=0;j<8;j++)
		{
			printf("%c",m[i][j]);
		}
		printf("\n");
	}
}
//采用递归函数解决实现八皇后回溯算法
//该函数求解当棋盘前row-1行已放置好皇后
	void EightQueen(int row)
	{
		int j;
		for(j=0;j<8;j++)    //在其中一列放置皇后
		{
			m[row-1][j]='Q';     //检查在该列放置皇后是否可行
			if(Check(row,j+1)==true)
			{
				if(row==8)Output();//若该列可放置皇后,且该列为最后一列,则找到一可行解,输出
				else EightQueen(row+1);//若该列可放置皇后,则向下一行继续搜索、求解
			}
    //取出该列的皇后,进行回溯,在其他列放置皇后
			m[row-1][j]='*';
		}
	}
//主函数
	void main()
	{
		EightQueen(1);   //求解八皇后问题
	}

5.程序运行结果:

打印出了所有解的结果,并输出解的数目。 至此,八皇后问题求解过程已全部结束。

Guess you like

Origin blog.csdn.net/qbyyds/article/details/120802131