回溯法总结

概念

回溯法是一种优选的搜索法,又称试探法。按选优条件向前搜索,已达到目标。但当搜索到某一步时,发现原选择并不优或者达不到目标,就退一步重新选择。这种走不通就退回再走的技术称为回溯法。

特点

1、出口

它的关键是出口语句放置的位置(建议出口语句放在递归函数的第一行),出口语句写在最前面,方便整个函数退出。

2、递归函数的参数

参数是随每一次的递归操作二发生改变的,二回溯的关键就是:如果当前操作行不通,如何回溯到上一部操作。解决办法就是不破坏当前值,即在当前值下一次递归调用时,把当前值按规律进行变换,变换的过程作为参数处低下去。

3、递归函数处理过程

如果当前递归过程额处理参数符合要求,则执行相关赋值或其他操作,然后转入下一次递归,如果下一次递归不能找到出口,则把之前相关赋值或其他操作重置为初始状态。

个人理解

1、构造解空间,即递归范围,在当前解空间中,便于搜索到答案

2、搜索策略:深度优先搜索

3、剪枝:去掉大量不必要的搜索以提高效率

关键特征

带优化的暴力穷举

总结

回溯法用到的核心思想就是递归,虽然过程逻辑清楚,而且执行效率很高,但缺点是逻辑清楚,必然代表抽象性很高。所以有时或是这样的情况,它的解题过程很容易看懂,但是要让自己动手写这个递归过程,发现很难下笔。

举例“八皇后”问题

该问题是国际西洋棋起手马克思·贝瑟尔于1848年提出,在8*8的国际象棋上,摆放8个皇后,使其不能互相共计,即任意两个皇后不能处在同一行、同一列、同一斜线上。问有多少种摆法。

代码实现

public class Main {
    private static int count = 0;    //记录成功的第几种可能
    private static int N = 8;    //几皇后

    public static void main(String[] args) {
        int[][] arr = new int[N][N];    //默认元素为0 1当皇后
        eightQueen(0, arr);    //打印八皇后所有可能的解 并且从第一行开始 0
    }

    //row [0,7]
    private static void eightQueen(int row, int[][] arr) {
        if (row == N) {    //row可以到达8 也就意味着前0~7行 每行都放有皇后
            count++;
            System.out.println("第" + count + "种:");
            for (int i = 0; i < arr.length; i++) {    //循环输出二维数组
                for (int j = 0; j < arr[i].length; j++) {
                    System.out.print(arr[i][j] + " ");
                }
                System.out.println();
            }
        } else {    //如果没有完成八皇后 复制一个副本 对其副本进行改变
            //做一个数组备份
            int[][] newArr = new int[N][N];
            for (int i = 0; i < arr.length; i++) {
                for (int j = 0; j < arr[i].length; j++) {
                    newArr[i][j] = arr[i][j];
                }
            }
            for (int col = 0; col < N; col++) {    //遍历 某行的每一列的元素
                if (noDangerous(row, col, newArr)) {    //判断这个位置是否可以放皇后 如果可以放
                    for (int c = 0; c < N; c++) {    //先清空这一行的元素(有可能以前这行有皇后 如果不清理则这行会有多个皇后)
                        newArr[row][c] = 0;
                    }
                    newArr[row][col] = 1;    //有皇后用1代表 没皇后用0代表
                    eightQueen(row + 1, newArr);//当前行找到皇后的位置后 在这个情况下 找下一行皇后放置的位置,这一个递归调用结束之后 在返回上一行 寻找其他的可能 在向重复上述的操作
                }
            }
        }
    }

    private static boolean noDangerous(int row, int col, int[][] newArr) {    //判断这个位置是否可以放皇后
        //正上
        for (int r = row - 1; r >= 0; r--) {
            if (newArr[r][col] == 1) {
                return false;
            }
        }
        //左上
        for (int r = row - 1, c = col - 1; r >= 0 && c >= 0; r--, c--) {
            if (newArr[r][c] == 1) {
                return false;
            }
        }
        //右上
        for (int r = row - 1, c = col + 1; r >= 0 && c < N; r--, c++) {
            if (newArr[r][c] == 1) {
                return false;
            }
        }
        return true;
    }
}

 

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值