八皇后问题是一个以国际象棋为背景的问题:如何能够在 8×8 的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。八皇后问题可以推广为更一般的n皇后摆放问题:这时棋盘的大小变为n×n,而皇后个数也变成n。当且仅当 n = 1 或 n ≥ 4 时问题有解。
求解:
#include <iostream>
using namespace std;
const int Q_number = 8 ;//皇后数量
int queens[Q_number][Q_number] = {0};//初始化数组
static int q_count = 0;//记录解数量
//用于输出结果 1表示皇后
void printBroad(){
for(int i =0;i < Q_number;i++){
for(int j = 0;j < Q_number;j++){
cout<<queens[i][j]<<" ";
}
cout<<endl;
}
cout<<endl;
}
//测试queue[row][column]是否符合条件
bool setQueen(int row,int column){
//从第一行开始摆放皇后 所以第一行不会出现不能摆放情况
if(row == 0){
queens[row][column] = 1;
return true;
}
//判断同一列是否存在皇后
for(int i = 0;i < row ;i++){
if(queens[i][column] == 1)
return false;
}
//用于是从第一行开始摆放 所以只需检验左上角和右上角两个方向即可
//检验左上角是否存在皇后
for(int i = row - 1,j = column - 1;i >= 0 && j >= 0;i--,j--){
if(queens[i][j] == 1){
return false;
}
}
//检验右上角
for(int i = row - 1,j = column + 1;j < Q_number && i >= 0;j++,i--){
if(queens[i][j] == 1)
return false;
}
//符合摆放皇后条件 将对应位置置1
queens[row][column] = 1;
return true;
}
//递归函数 求解第row行摆放皇后条件
void solve(int row){
//遍历完成 输出结果
if(row == Q_number){
q_count++;
printBroad();
return ;
}
//遍历第row行 寻找符合条件的皇后位置
for(int i = 0;i < Q_number;i++){
//试探row行 i列是否符合条件
if(setQueen(row,i)){
//符合条件 求解下一行
solve(row +1);
}
//row行 i列情况试探完毕 将对应位置重置为0 防止干扰下次结果
queens[row][i] = 0;
}
}
int main(){
solve(0);//开始求解
cout<<"count:"<<q_count<<endl;
system("pause");
return 0;
}
代码注释应该是比较详细的,求解的关键是理解递归函数。通过递归函数遍历每一行,寻找符合条件的解。
其实八皇后问题很早就听说过,但是由于算法方面实在很菜,一直不会求解。最近开始学习算法,在leetcode上又看到这个经典的皇后问题,于是下决心要求出结果。由于这个问题实在经典,google一下之后出来一堆求解方法,都是大同小异,基本都是回朔法(backtracking)求解,具体有递归和非递归两种解法。由于最近在leetcode上刷了一些二叉树的题,基本都是递归求解,所以索性也用递归求解,经过一下午的努力,终于求出了结果,激动地不行啊。lol
最后再说下递归。在刚开始学习递归的时候其实我是拒绝的,因为递归又不好理解,效率又低(好吧,主要是理解不了)。所以在平时写程序的时候基本不用递归。后来学习数据结构的时候接触到二叉树,要写算法遍历树(前中后序遍历),书上的解法就是递归解法,那时候开始感受到递归解法的简洁和强大,简简单单的的几行代码就可以完成这么多的计算。最近又开始重学算法,在leetcode刷题碰到很多二叉树的问题,刚开始很头疼,写一大段代码,最后结果还是错的,无奈只能去看discuss里各位AC的大神的解法,里面有很多优秀的代码,有的甚至只要一行就能解决(虽然只是easy的问题),当时我就被震惊了,这TM还能这么简单,于是,每次碰到的问题我都先考虑能不能用递归求解,刷了一些题目之后稍微有了一些感觉,递归其实就是将一个大问题分解成相似的小问题,通过解决一个个小问题,最后解出大问题,比如八皇后问题,一下子求解所有皇后摆放位置很困难,所以我们通过递归先解决第一个皇后位置,然后第二个,第三个知道第N个。而且,递归也是一些别的算法,比如,分治,动态规划的基础。入门递归之后接下来就可以开始学习分治,动态规划之类的算法了,未来的路还很漫长。