八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。

C语言实现的代码如下:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#define N 8
typedef struct Pos
{
int x_pos;
int y_pos;
}Pos;
int counter = 0;
void Init_Board(char board[N+2][N+2])
{
int i = 0;
int j = 0;
for(i=0;i<N+2;i++)
{
board[i][0] = '#';
board[0][i] = '#';
board[i][N+1] = '#';
board[N+1][i] = '#';
}
for(i=1;i<=N;i++)
{
for(j=1;j<N+1;j++)
{
board[i][j] = ' ';
}
}
}
void Display_Board(char board[N+2][N+2])
{
int i = 0;
int j = 0;
for(i=0;i<N+2;i++)
{
for(j=0;j<N+2;j++)
{
if(j!=N+1)
{
printf(" %c |",board[i][j]);
}
else
{
printf(" %c ",board[i][j]);
}
}
printf("\n");
if(i!=N+1)
{
printf("---|---|---|---|---|---|---|---|---|---\n");
}
}
}
int Check(char board[N+2][N+2],int row,int j)
{
Pos pos[3] = {{-1,-1},{-1,0},{-1,1}};
int ni = 0;
int nj = 0;
int k = 0;
int ret = 1;
for(k=0;k<3;k++)
{
ni = row;
nj = j;
while(ret && board[ni][nj] != '#')
{
if(board[ni][nj] == '*')
{
ret = 0;
}
ni += pos[k].x_pos;
nj += pos[k].y_pos;
}
}
return ret;
}
void Find(char board[N+2][N+2],int row)
{
int j = 0;
if(row > N)
{
counter++;
printf("\n第%d种排列:\n",counter);
Display_Board(board);
}
else
{
for(j=1;j<=N;j++)
{
if(Check(board,row,j))
{
board[row][j] = '*';
Find(board,row+1);
board[row][j] = ' '; //下一行不能放,说明当前行放的不对,将其清空继续查找
}
}
}
}
int main()
{
char board[N+2][N+2];
Init_Board(board);
Find(board,1);
printf("共有%d种排列方式\n\n",counter);
return 0;
}
执行的部分结果如下图所示,共有92种排列方式。


探讨了八皇后问题的历史背景及其解决方案,通过C语言实现的代码详细展示了如何使用回溯算法解决这一经典问题,最终找到了所有92种可能的布局。
399

被折叠的 条评论
为什么被折叠?



