八皇后问题算是一个回溯算法的典型案例。虽然我不太懂回溯,但该问题很有内味(。・∀・)ノ゙,下面描述一下我的解法
八皇后问题指在一个8×8的棋盘上,摆放八个皇后,要求这八个皇后不能互相攻击,每个皇后的攻击范围为同一行、同一列、同一个斜线,也就是任意两个皇后不能处于同一行、同一列、同一斜线上,问题就是这八个皇后有多少种站法。(我懒得用主对角线、副对角线什么的解释了,大家都懂( ̄▽ ̄)")
显然每一行、每一列都有且仅有一个皇后,8×8的棋盘比作8阶矩阵
若两个元素位于同一主对角线,则他们行数差等于列数差;若两个元素位于同一副对角线,则他们行数差加列数差为0。OK,数学准备工作完成,具体参考代码注释吧
#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
int chess[9][9], queen[9], sum = 0;//皇后数组下标为该皇后所站行数,值为所站列数
bool can_place(int row, int column) {//row行,column列能否放置皇后
for(int i = 1; queen[i] != 0; i++) {//i为已站好皇后行数,queen[i]为他们所在列数
if(column == queen[i] || row - i == column - queen[i] || row - i + column - queen[i] == 0) {
return false;//同一列、同一主对角线、同一副对角线均不可
}
}
return true;
}
void place_queen(int row) {//在第row行放置第row个皇后
if(row == 9) { //八个皇后已放置完毕
cout << "第" << ++sum << "种:" << endl;
for(int a = 1; a < 9; a++) {
for(int b = 1; b < 9; b++) {
cout << chess[a][b] << " ";
}
cout << endl;
}
cout << endl;
return;//该句可有可无,提高一丢丢效率吧
}
for(int column = 1; column <= 8; column++) {
if(can_place(row, column)) {
queen[row] = column;
chess[row][column] = 1;//0表示该位置无皇后,1表示有皇后
place_queen(row + 1);//每次调用该递归会确定一种八皇后的站法
chess[row][column] = 0;//接上句,确定一种站法后需要归零
queen[row] = 0;
}
}
return;
}
int main() {
place_queen(1);
cout << sum << endl;
return 0;
}
以前学习C的时候,毫无算法概念,用过暴力求解,还真就做出来了,但耗时感人。其实我现在仍然觉得暴力出奇迹