回溯算法
回溯的描述:
回溯算法将解空间看作一定的结构,通常为树形结构,一个解对应于树中的一片树叶。算法从树根(即初始状态出发),尝试所有可能到达的结点。当不能前行时就后退一步或若干步,再从另一个结点开始继续搜索,直到尝试完所有的结点。也可以用走迷宫的方式去理解回溯,设想把你放在一个迷宫里,想要走出迷宫,最直接的办法是什么呢?没错,试。先选一条路走起,走不通就往回退尝试别的路,走不通继续往回退,直到走遍所有的路,并且在走的过程中你可以记录所有能走出迷宫的路线。
回溯与八皇后问题
在国际象棋中,皇后是最强大的一枚棋子,可以吃掉与其在同一行、列和斜线的敌方棋子。八皇后问题是这样一个问题:将八个皇后摆在一张8*8的国际象棋棋盘上,使每个皇后都无法吃掉别的皇后,一共有多少种摆法?
如果使用暴力算法的话要在8*8个格子中选择8个格子来摆放皇后,一共要尝试C864次,十亿级别的尝试次数!
稍加分析,我们可以得到一个不那么暴力的办法,显然,每行每列最多只能有一个皇后,如果基于这个事实进行暴力破解,那结果会好得多。安排皇后时,第一行有8种选法,一旦第一行选定,假设选为(1,i),第二行只能选(2,j),其中j!=i,所以有7种选法。以此类推,需要穷举的情况有8!=40320种。
我们先降下规模来看看4皇后问题:4个皇后在4*4的格子里各自安排不打架,一共有多少种安排方法?
试着来穷举一下,真的需要4!=24次尝试吗?现在我们把第一个皇后放在第一个格子,被涂黑的地方是不能放皇后的。
第二行的皇后只能放在第三格或第四格,按照回溯我们要先尝试放在第三格,则:
这样第三位皇后无论放哪里都难逃被吃掉的厄运。于是在第一个皇后位于1号,第二个皇后位于3号的情况下问题无解。我们只能返回上一步来,给2号皇后换个位置。
显然,第三个皇后只有一个位置可选。当第三个皇后占据第三行蓝色空位时,第四行皇后无路可走,于是发生错误,返回上层调用(3号皇后),而3号也别无可去,继续返回上层调用(2号),2号已然无路可去,继续返回上层(1号),于是1号皇后改变位置如下,继续搜索。
话说到这里,我们对“回溯法”已经有了基本概念。然而所谓知易行难,理解算法和将算法写出来完全是两回事。下面来看看代码:
代码不长,注释很多
#include <iostream> using namespace std; bool isOk(int c[], int row, int n); //函数:判断能否在第row行第c[row]列插入一个皇后 void queen(int row, int c[], int n, int& total); //函数:回溯的核心部分 int main() { int n; //皇后的数量 cout << "Please enter the number of queen:\n"; cin >> n; int* c = new int[n]; //记录皇后的位置,例如c[i]的值为j表示第i行的皇后放在第j列 int total = 0; //解决方案的种数 queen(0, c, n, total); cout << "The number of solution is:\n" << total; return 0; } void queen(int row, int c[], int n, int& total) { if (row == n) //当row等于n的时候表示皇后全部摆放完毕 { for (int i = 0; i < n; i++) cout << c[i] << " "; cout << endl; total++; } else //皇后还未摆放完,则执行下面程序 { //遍历所有的列,看看第row行皇后可以放在第几列 for (int col = 0; col < n; col++) { c[row] = col; //如果可以放在row行col列则继续摆放下一行 if (isOk(c, row, n)) queen(row+1, c, n, total); //如果不可以放在row行col列则试试下一列 } //如果循环了所有的列都不能摆放,则会回溯到前一层函数改变上一行皇后的摆放 } } bool isOk(int c[], int row, int n) { for (int i = 0; i < row; i++) { //第row行皇后不能和任意之前的皇后在同一列或 \方向或 / 方向 if (c[i] == c[row] || c[row]-row == c[i]-i || c[row]+row == c[i]+i) return false; } return true; }
算法是逐行安排皇后的,其参数row为现在正执行到第几行(row是从0开始的,0表示第一行)。n是皇后数。
参考博客:https://www.cnblogs.com/bigmoyan/p/4521683.html