什么是八皇后
八皇后是一个古老的经典问题:如何在一张国际象棋的棋盘上,摆放8个皇后,使其任意两个皇后互相不受攻击。
1850年,Franz Nauck 给出了第一个解,并将其扩展成了“ n皇后 ”问题,即在一张 n x n 的棋盘上,如何摆放 n 个皇后,使其两两互不攻击。
个人分析问题的思路
- 明确规则:在国际象棋中,一个皇后的攻击范围如图所示:
- 分析问题:本质上八皇后问题可以转换为一个平面上的坐标问题,每个皇后占一个坐标,且每个皇后坐标相互之间又满足约束条件:不在同一行、同一列和同一对角线,即每个皇后的横纵坐标绝对不一样,且需要保证对角线上没有其他皇后。
- 解决思路:最简单的方法就是不断尝试,穷尽枚举法,以行为单位或以列为单位,每次在一行(列)中放下一个皇后,然后在另一行放入,并同时检测是否满足约束条件,若不满足则重新尝试,回溯到上一行,或某一行重新开始。
核心思想:枚举(通过循环来实现),具体使用递归实现(也可以使用8重循环,但递归更方便,且逻辑上更清晰,只需要明确要设立终止条件),回溯(通过判断来看是否满足约束条件,若不满足则重新尝试)
参考代码
#include <stdio.h>
#include <math.h>
#define QueenNumber 8//将8改为其他数值可以变为n皇后问题
int Total = 0;//存储总共有多少种方法
int Loc[QueenNumber];//通过数组来模拟坐标,以下标位置为横坐标
//判断是否满足约束条件
bool Check(int row)
{
for (int i = 0;i != row; i++)
{
//判断两个皇后是在同一行,同一列或者在同一对角线
if(Loc[row]==Loc[i] || row-Loc[row]==i-Loc[i] || row+Loc[row]==i+Loc[i])
{
return false;
}
}
return true;
}
//主要通过递归实现
void Queen(int row)
{
if (row==QueenNumber)
{
//若成功则方法总数加1,同时打印摆放位置
Total++;
for (int i=0;i<QueenNumber;i++)
{
printf("(%d,%d) ",i+1,Loc[i]+1);
}
putchar('\n');
}
else
{
for (int col = 0; col !=QueenNumber ; col++)
{
Loc[row]=col;
if (Check(row))
{
Queen(row+1);
}
}
}
}
int main()
{
Queen(0);//从第一行开始,从数组的角度则为下标0开始
printf("%d",Total);
return 0;
}