简介:
八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。计算机发明后,有多种计算机语言可以解决此问题。
代码实现(C语言):
#include <stdio.h>
int count = 0; // 记录答案个数
// n是当前列
// 危险返回1
int Danger(int row, int n, int (*chess)[8])
{
// 判断列
for (int i = 0; i < 8; i++)
{
if (chess[i][n] == 1)
return 1;
}
// 判断左上
int x = row, y = n;
while ( x>=0 && y>=0)
{
if (chess[x][y] == 1)
return 1;
x--; y--;
}
// 判断左下
x = row; y = n;
while ( x<8 && y>=0 )
{
if (chess[x][y] == 1)
return 1;
x++; y--;
}
// 判断右上
x = row; y = n;
while ( x>=0 && y<8)
{
if (chess[x][y] == 1)
return 1;
x--; y++;
}
// 判断右下
x = row; y = n;
while ( x<8 && y<8)
{
if (chess[x][y] == 1)
return 1;
x++; y++;
}
return 0;
}
/*
row: 表示行
n: 表示列
(*chess)[8]: 指向数组的每一行
*/
void eightQueen(int row, int n, int (*chess)[8])
{
if (row == 8)
{
count ++;
printf("第 %d 种.\n", count);
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
printf("%d ", chess[i][j]);
}
printf("\n");
}
printf("\n");
}
else
{
for (int i = 0; i < 8; i++)
{
if (!Danger(row, i, chess)) // 这个位置危险 则返回1,否则返回 0
{
*(*(chess+row)+i) = 1;
eightQueen(row+1, n, chess);
}
*(*(chess+row)+i) = 0;
}
}
}
int main(void)
{
int chess[8][8] = {0};
eightQueen(0, 8, chess);
printf("共 %d 种.", count);
return 0;
}
输出结果:
第 1 种.
1 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 1
0 0 0 0 0 1 0 0
0 0 1 0 0 0 0 0
0 0 0 0 0 0 1 0
0 1 0 0 0 0 0 0
0 0 0 1 0 0 0 0
......
第 92 种.
0 0 0 0 0 0 0 1
0 0 0 1 0 0 0 0
1 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0
0 0 0 0 0 1 0 0
0 1 0 0 0 0 0 0
0 0 0 0 0 0 1 0
0 0 0 0 1 0 0 0
共 92 种.