快捷搜索: 王者荣耀 脱发

用栈解决N皇后问题(超详细注释、C/C++实现)

用栈解决N皇后问题(超详细注释、C/C++实现)

目的:

深入掌握栈应用的算法设计

内容:

编写一个程序,求解n皇后问题,即在n*n方格棋盘上放置n个皇后,要求每个皇后不同行、不同列、不同左右对角线

  1. 皇后个数n由用户输入,其值不能超过20,输出所有的解
  2. 采用类似于栈求解迷宫问题的方法

GitHub地址(包含.cpp文件和可执行程序exe)

源代码(经VS2015、devC++编译器运行通过)

#include "stdio.h"    
#include "stdlib.h"   
#include "io.h"  
#include "math.h"  
#include "time.h"

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 20 /* 存储空间初始分配量 */

typedef int Status;
typedef int SElemType; /* SElemType类型根据实际情况而定,这里假设为int */

					   /* 顺序栈结构 */

typedef struct
{
          
   
	SElemType data[MAXSIZE];
	int top; /* 用于栈顶指针 */
}SqStack;

int count = 0;



/*调用此方法用于检测是否符合N皇后规则*/
int placeQueen(SqStack s, int i, int j) {
          
    //测试(i、j)是否与1->i-1皇后有冲突(i:行)

		/*a为函数的返回值,0是否1是是*
		 *k为列数,默认为第一列
		 */								
		int a = 0;  
		int k = 1;



		/*进来的是第一行*/
		if (i == 1) 
		{
          
   
			/*当场确定-->第一行第一个位置可放*/
			a = 1;		
			return a;
		}


		/*如果不是第一行,则i到这里肯定>=2*/
		while (k <= i - 1)				 //j=1到k-1是已经放置了皇后的列
		{
          
   
			/*fabs()是对浮点数取绝对值
			 *验证N皇后规则核心算法,s.data[k] == j-->同列
			 fabs(j - s.data[k] == fabs(i - k)-->同对角
			*/
			if ((s.data[k] == j) || fabs(j - s.data[k] == fabs(i - k)))  
			{
          
   
				/*无合适位置*/
				a = 0;
				return a;
			}
			else
			k++;
		}
		
		a = 1;
		return a;
}



void queen(int n, SqStack &s) {
          
   
	int i, j, k;
	int  find = 0;

	/*初始化栈顶指针*/
	s.top = 0;			
	/*行作为栈顶指针进栈,初始值为1*/
	s.top++;		
	/*列作为栈顶指针进栈,初始值为1*/     /*--->(1,1)进栈*/
	s.data[s.top] = 1;


	/*条件:栈不空,循环操作-->开启探寻*/
	while (s.top>0)    
		{
          
   
			/*i为行数标志,可作为参数使用,也用于判断是否走尽*/
			i = s.top;    
		
		
			/*当前皇后行数s.top == n-->已经处理完最后一个皇后,所有皇后均放好,输出一个解
				*注意:并不会结束程序,因为N皇后问题有多个解
			*/
			if (s.top == n) {
          
   
				printf("第%d个解:", ++count);
				for (k = 1; k < s.top; k++)
					printf("(%d,%d)", k, s.data[k]);
				printf("
");
			}

			find = 0;

			/*在i+1行探寻一个放皇后的位置(i+1,j)*/
			for (j = 1; j <= n; j++)
					/*条件正确,表明探寻到一个合适的位置-->行列入栈*/
				if (placeQueen(s, i + 1, j)) {
          
   
					/*行+1入栈*/
					s.top++;
					/*列入栈*/
					s.data[s.top] = j;
					/*找到标志,如果走完此for循环,标志未变更,则走到下一段代码*/
					find = 1;
					/*跳出for循环*/
					break; 
				}


			/*当前行无目标-->退栈*/					
					if (find == 0) {
          
   
					while (s.top > 0) {
          
   
						/*1-已到达最末列无位置即本行无可放位置,退栈*/
						if (s.data[s.top] == n) 
							/*形象来讲,行-1*/
							s.top-- ;

						/*2-未走完全位置,从下位置出发探寻*/
						for (j = s.data[s.top] + 1; j <= n; j++)
								  /*在后续列中探寻到合适的位置*/
							if (placeQueen(s, s.top, j))
							{
          
   
									/*列入栈*/
								s.data[s.top] = j;  
								break;
							}


						/*当前皇后在本行没有可放位置,退栈
						*/
						if (j > n)
							s.top--;
						else
							break; 
							
				}}

	}}

int main()
{
          
   
	
	SqStack s;
	int n; 

		printf("请输入需要解决几皇后问题...
");
		scanf("%d", &n); 
	

		printf(" %d皇后问题求解如下:
", n);
		queen(n,s); 
		printf("
"); 
		
		system("pause"); 
	return 0;

}

运行结果

经验分享 程序员 微信小程序 职场和发展