算法训练 || 八皇后问题(递归回溯)
首先说明一下递归和回溯的区别:
- 递归是一种数据结构;
- 回溯是一种算法思想,也可理解为一个解决问题的工具。
一、回溯算法
回溯算法,简单的说,就是一条路走到黑,无路可走了就回头,从分叉路口找另一条路继续走到黑,如此反复,直到所有路都走完。
这个算法思想跟跟深度优先搜索算法(DFS)类似,但两者也有不同之处,体现在:
- 访问序
回溯算法对每一个元素的访问都有一个序,不能使用 visited 记录,因为不仅仅是记录 “是否被访问过” 这么简单;而DFS算法对访问的“序”没有提出要求,只要访问过该结点(元素),就用visited记录下即可。 - 适用场景
回溯是遍历问题空间寻找解决方案的方法,而DFS是一种遍历实际图或者树结构然后求值的方法。
二、八皇后问题
问题描述:
八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯・贝瑟尔于 1848 年提出:
在 8×8 格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
这个问题的难点在于一个皇后放置之后会对下一个皇后位置的放置点产生影响(道路堵塞),下面用表格简单描述一下这一场景,
- 放一个皇后及它皇后所引起的道路堵塞(用黑色填充表示被堵塞的道路)
- 假设在第3行的空白格放置下一个皇后(用蓝色填充表示被堵塞的道路),则出现
可见每放置一个皇后对下一个皇后位置放置的影响是很大的。
在这里可能有些小伙伴会想到用暴力算法求解,但是暴力算法在这里的思路虽然行得通,但是由于数据量太大,在程序竞赛时往往容易造成超时,而且暴力算法的效率较低,所以这里采用一种效率更高效的算法:回溯算法。通过递归函数的调用,很快就能计算出问题的答案。
具体代码如下:
public class 八皇后回溯递归 {
static int count=0;
static int [][]arr=new int[8][8];
public