用栈解决N皇后问题(超详细注释、C/C++实现)
用栈解决N皇后问题(超详细注释、C/C++实现)
目的:
深入掌握栈应用的算法设计
内容:
编写一个程序,求解n皇后问题,即在n*n方格棋盘上放置n个皇后,要求每个皇后不同行、不同列、不同左右对角线
- 皇后个数n由用户输入,其值不能超过20,输出所有的解
- 采用类似于栈求解迷宫问题的方法
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;
}
