问题描述:在 8×8 格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
解题思路:最简单的做法就是穷举法,将8^8 =16,777,216 种情况全部穷举一遍,判断是否符合要求,显然这种方法太过于耗费时间,不可取,于是引入了回溯算法,虽然回溯算法也是暴力搜索,但是优于穷举法。思路是,先将第一列放上一个皇后,在第二列不冲突的位置上放上另一个皇后,在在第三列不冲突的位置方式第三个皇后,依次类推,如果下一个皇后没有一个安放的位置,则返回上一步,放在第二个不冲突的位置上,不过不满足,依次退回。简单的C语言代码如下所示:
#include <stdio.h>
#include <stdlib.h>
#define N 8
char Board[N + 2][N + 2] ; //! 棋盘数组
int SolveCount = 0 ; //! 解法计数
//! 打印显示棋盘
void Display_Board(void)
{
int row , col ;
for(row = 0 ; row < N + 2 ; ++ row)
{
for(col = 0 ; col < N + 2 ; ++ col)
{
printf(" %c" , Board[row][col]) ;
}
printf("\n") ;
}
}
//! 初始化棋盘
void Init_Board(void)
{
int row , col ;
for(row = 0 ; row < N + 2 ; ++ row)
{
for(col = 0 ; col < N + 2 ; ++ col)
{
if(row > 0 && row < N + 1 && col > 0 && col < N + 1)
Board[row][col] = ' ' ;
else
Board[row][col] = '#' ;
}
}
}
//! 检测该位置的皇后是否冲突
int Check_Board(int row , int col)
{
int nCol = col - 1 , nCol1 = col + 1 ;
for(-- row ; row > 0 ; -- row , -- nCol , ++ nCol1)
{
if(Board[row][col] == '*') return 0 ;
if(nCol > 0)
{
if(Board[row][nCol] == '*') return 0 ;
}
if(nCol1 < N + 1)
{
if(Board[row][nCol1] == '*') return 0 ;
}
}
return 1;
}
//! 求解棋盘
void Solve_Boad(int row)
{
if(row > N) //! 判断是否所有位置已安放完成
{
SolveCount ++ ;
printf("Solution: %d\n" , SolveCount) ;
Display_Board() ;
getchar() ; //! 按下Enter键获取下一种解法
}
else
{
int col = 1;
for( ; col <= N ; ++ col)
{
if(Check_Board(row , col))
{
Board[row][col] = '*' ;
Solve_Boad(row + 1) ;
Board[row][col] = ' ' ;
}
}
}
}
int main()
{
Init_Board() ;
Solve_Boad(1) ;
return 0;
}