关于递归和回溯
来源:互联网 发布:linux u盘启动 编辑:程序博客网 时间:2024/04/27 18:14
void DFSTraverse() { flag = new boolean[number]; for (int i = 0; i < number; i++) { if (flag[i] == false) {// 当前顶点没有被访问 DFS(i); } } } // 图的深度优先递归算法 void DFS(int i) { flag[i] = true;// 第i个顶点被访问 System.out.print(vertexs[i] + " "); for (int j = 0; j < number; j++) { if (flag[j] == false && edges[i][j] == 1) { DFS(j); } } }
1、递归
递归方法肯定有回溯的过程,即原路返回,这是递归方法的特质,比如上面的dfs。执行过程为:遍历完所有的顶点后,会跳出void DFS(int i)方法中的for循环,下一步它会跳入for循环,参数的值上一步参数的值,然后让j++,判断j是否跳出for循环。
如果没有则跳出for循环,下一步又跳回到循环,参数值为上上步的值然后继续之前动作。如果有,则判断if语句,不符合if语句的,即它的下一个相连的顶点已经被标记,注意此时是判断它的下一个顶点,并不是所有的顶点,此处是回溯法应用的精妙之处,下面会讲到。如果下一个顶点符合if语句,即有相连的顶点没有被标记则继续访问它的相连顶点,访问完之后再回溯。回溯过来,再访问下下个相连顶点,如果没有,则返回。
此处的回溯的精妙之处在于它按原路返回,然后因为它还在for循环里,所有判断它的下一个相连的顶点(不会重复访问已经访问过的相邻顶点),这是回溯的基础。典型应用
典型应用时8皇后问题,现摘抄一段可以调试的算法
回溯法:也称为试探法,它并不考虑问题规模的大小,而是从问题的最明显的最小规模开始逐步求解出可能的答案,并以此慢慢地扩大问题规模,迭代地逼近最终问题的解。这种迭代类似于穷举并且是试探性的,因为当目前的可能答案被测试出不可能可以获得最终解时,则撤销当前的这一步求解过程,回溯到上一步寻找其他求解路径。
为了能够撤销当前的求解过程,必须保存上一步以来的求解路径,这一点相当重要。
光说不做没意思,用学过的算法题来运用一下。
N 皇后问题:在一个 N * N 的国际象棋棋盘中,怎样放置 N 个皇后才能使 N 个皇后之间不会互相有威胁而共同存在于棋局中,即在 N * N 个格子的棋盘中没有任何两个皇后是在同一行、同一列、同一斜线上。
求解思路:最容易想到的方法就是有序地从第 1 列的第 1 行开始,尝试放上一个皇后,然后再尝试第 2 列的第几行能够放上一个皇后,如果第 2 列也放置成功,那么就继续放置第 3 列,如果此时第 3 列没有一行可以放置一个皇后,说明目前为止的尝试是无效的(即不可能得到最终解),那么此时就应该回溯到上一步(即第 2 步),将上一步(第 2 步)所放置的皇后的位置再重新取走放在另一个符合要求的地方…如此尝试性地遍历加上回溯,就可以慢慢地逼近最终解了。
需要解决的问题:如何表示一个 N * N 方格棋盘能够更有效?怎样测试当前所走的试探路径是否符合要求?这两个问题都需要考虑到使用怎样的数据结构,使用恰当的数据结构有利于简化编程求解问题的难度。
为此,我们使用以下的数据结构:
int column[col] = row 表示第 col 列的第 row 行放置一个皇后
boolean rowExists[i] = true 表示第 i 行有皇后
boolean a[i] = true 表示右高左低的第 i 条斜线有皇后(按 → ↓ 顺序从1~ 2*N -1 依次编号)
boolean b[i] = true 表示左高右低的第 i 条斜线有皇后(按 → ↑ 顺序从1~ 2*N -1 依次编号)
对应这个数据结构的算法实现如下:
/* 回溯法求解 N 皇后问题 * @author haolloyin */ public class N_Queens { // 皇后的个数 private int queensNum = 4; // column[i] = j 表示第 i 列的第 j 行放置一个皇后 private int[] queens = new int[queensNum + 1]; // rowExists[i] = true 表示第 i 行有皇后 private boolean[] rowExists = new boolean[queensNum + 1]; // a[i] = true 表示右高左低的第 i 条斜线有皇后 private boolean[] a = new boolean[queensNum * 2]; // b[i] = true 表示左高右低的第 i 条斜线有皇后 private boolean[] b = new boolean[queensNum * 2]; // 初始化变量 private void init() { for (int i = 0; i < queensNum + 1; i++) { rowExists[i] = false; } for(int i = 0; i < queensNum * 2; i++) { a[i] = b[i] = false; } } // 判断该位置是否已经存在一个皇后,存在则返回 true private boolean isExists(int row, int col) { return (rowExists[row] || a[row + col - 1] || b[queensNum + col - row]); } // 主方法:测试放置皇后 public void testing(int column) { // 遍历每一行 for (int row = 1; row < queensNum + 1; row++) { // 如果第 row 行第 column 列可以放置皇后 if (!isExists(row, column)) { // 设置第 row 行第 column 列有皇后 queens[column] = row; // 设置以第 row 行第 column 列为交叉点的斜线不可放置皇后 rowExists[row] = a[row + column - 1] = b[queensNum + column - row] = true; // 全部尝试过,打印 if(column == queensNum) { for(int col = 1; col <= queensNum; col++) { System.out.print("("+col + "," + queens[col] + ") "); } System.out.println(); }else { // 放置下一列的皇后 testing(column + 1); } // 撤销上一步所放置的皇后,即回溯 rowExists[row] = a[row + column - 1] = b[queensNum + column - row] = false; } } } // 测试 public static void main(String[] args) { N_Queens queen = new N_Queens(); queen.init(); // 从第 1 列开始求解 queen.testing(1); } }
- (1,1) (2,5) (3,8) (4,6) (5,3) (6,7) (7,2) (8,4)
- (1,1) (2,6) (3,8) (4,3) (5,7) (6,4) (7,2) (8,5)
- (1,1) (2,7) (3,4) (4,6) (5,8) (6,2) (7,5) (8,3)
- ... ...
- ... ...
- (1,8) (2,2) (3,4) (4,1) (5,7) (6,5) (7,3) (8,6)
- (1,8) (2,2) (3,5) (4,3) (5,1) (6,7) (7,4) (8,6)
- (1,8) (2,3) (3,1) (4,6) (5,2) (6,5) (7,7) (8,4)
- (1,8) (2,4) (3,1) (4,3) (5,6) (6,2) (7,7) (8,5)
- (1,2) (2,4) (3,1) (4,3)
- (1,3) (2,1) (3,4) (4,2)
有时间的话将输出的结果打印为直观一点的符号形式或界面形式更好。
- 关于递归和回溯
- 回溯和递归区别
- 递归和回溯法
- 递归和回溯
- 关于递归和回溯的说明以及8皇后问题的递归流程分析
- 回溯法之递归回溯和迭代回溯
- 穷举递归和回溯算法
- 递归和回溯题目四则
- leetcode--递归、回溯和分治
- N皇后问题的非递归回溯和递归回溯
- 关于回溯算法的递归与非递归解法
- 递归回溯
- 递归回溯
- 递归回溯
- 递归回溯
- 穷举递归和回溯算法终结篇
- 回溯 八皇后问题(递归和非递归)
- 子集和的递归解法和回溯法
- NPY and girls-HDU5145莫队算法
- Hibernate连接mysql数据库
- 记录一个简单的ASM程序破解过程
- 注释文档
- fragment处理物理返回键
- 关于递归和回溯
- swift 中的delegate 写法
- 神通广大的CSS3选择器
- Sublime Text -Sidebar 背景色调整为黑色攻略~
- Cocos Studio如何做分辨率适配
- 启动出错:roslaunch turtlebot_gazebo amcl_demo.launch map_file:=/tmp/my_map.yaml
- maven 之项目部署
- iOS使用Charles(青花瓷)抓包并篡改返回数据图文详解
- 蓝缘管理系统简介