前言:8皇后耳熟能详,参考链接百度百科——八皇后。把8扩展成N,就是N皇后问题。我以下给出了解决N皇后的3个经典算法的思想和源代码(业界良心)!
1 数据结构
一个二维的棋盘,可以用一维的向量存储,我使用C++ STL中的std::vector。假设是8皇后,那么vector的大小是8,代表棋盘中的8行。vector[i] = j (0~7),代表第 i 行的皇后在第 j 列,一个vector就是一个棋盘,统称为“状态”。这样子做很巧妙地成功把二维棋盘当作一维向量保存,降低了维数。
在遗传算法中,为了保存一个种群(很多个棋盘),使用std::vector< vector< int>>,相当于二维的向量,即“向量里面的元素是一个向量”。使用STL中的vector,可以全方位提升程序的质量,比如安全性,鲁棒性等。
图:项目的文件依赖关系
2 回溯法
//检测把皇后放置在棋盘位置 ( row, column ) 是否和前 row-1 行放置的皇后存在互相攻击的情况
//@param: row 是行数,column是列数
bool NQueensBacktrack::Check(int row, int column)
For i: 0 to row-1 do
If 对角线方向互相攻击,或者垂直方向互相攻击
返回 false
End if
End for
返回 true
End
回溯法(递归)有两种方法:第一种是求出所有解,第二种是求出第一个解就退出。两者之间只有两三行代码的区别。
第一种方法
//@param: row 是行数
void NQueensBacktrack::Backtrack(int row)
For column: 0 to QueenNumber-1 do
If 检测到位置(row, column)没有和皇后们互相攻击
把一个皇后放到(row, column)
If 这个皇后是在最后一行
打印此时的棋盘
End if
Backtrack(row +1),从下一行开始继续递归
End if
End for
End
第二种方法
//@param: row 是行数
//Flag 初始化为 flase
void NQueensBacktrack::Backtrack(int row)
If Flag 等于 ture