• 回溯算法的了解


    什么是回溯法

    • 回溯算法本质就是一个暴力枚举的思路(动态是求最值这个类型,是有选择的枚举,具有重叠结构,和最优子结构)
    • 穷举的过程就遍历一颗多叉树的过程
    • 回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解 条件时,就回溯返回,尝试别的路径。
    • 回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点 称为回溯点。也可以称为剪枝点,所谓的剪枝,指的是把不会找到目标,或者不必要的路径裁剪掉。
    • 许多复杂的,规模较大的问题都可以使用回溯法,有通用解题方法的美称。
    • 在包含问题的所有解的解空间树中,按照深度优先搜索的策略,从根结点出发深度探索解空间树。当探索到某一结点时,要先判断该结点是否包含问题的解,如果包含,就从该结点出发继续探索下去,如果该结点不包含问题的解,则逐层向其祖先结点回溯。(其实回溯法就是对隐式图的深度优先搜索算法)。
    • 若用回溯法求问题的所有解时,要回溯到根,且根结点的所有可行的子树都要已被搜索遍才结束。 而若使用回溯法求任一个解时,只要搜索到问题的一个解就可以结束。
    • 除过深度优先搜索,常用的还有广度优先搜索。

    全排列问题 

     

    1. class Solution {
    2. List> res=new LinkedList<>();
    3. public List> permute(int[] nums) {
    4. LinkedListtrack=new LinkedList<>();
    5. backtrack(nums,track);
    6. return res;
    7. }
    8. private void backtrack(int[] nums, LinkedList track) {
    9. if (track.size()==nums.length){
    10. res.add(new LinkedList<>(track));
    11. return;
    12. }
    13. for (int i = 0; i
    14. //排除不合法的选择 剪枝
    15. if (track.contains(nums[i])){
    16. continue;
    17. }
    18. //做选择
    19. track.add(nums[i]);
    20. //进入下一层的决策树
    21. backtrack(nums,track);
    22. //取消选择,返回上一层的树、
    23. track.removeLast();
    24. }
    25. }
    26. }

     

    • 只要遍历到叶子节点,这个路径就是一个排列的组合 ,这里有剪枝的操作,就是当遇到链表中出现的数字,我们就不需要往下递归了

    N皇后问题

     

    • 首先我们去考虑,如果不考虑列之间和斜线之间的冲突问题,那就是让我们去每一行去放一个皇后

    • 如果这样去考虑,相当于第一列代表1,第二列代表2,第三列代表3, 可以选1 1 1,1 1 2,1 1 3,1 2 1.....

    这种考虑的多叉树

    •  走到叶子节点的路径就是我们的放置方法,我们在全部的方法中满足列和列之间不能攻击,列与列之间不能攻击的问题
    • 下面就是利用不能选择的条件去剪枝

    • 依靠这三个条件来判断能不能添加,进行剪枝 
    1. class Solution {
    2. List> res=new LinkedList<>();//棋盘的存储
    3. public List> solveNQueens(int n) {
    4. char[][] board = new char[n][n];
    5. for (char[] c : board) {
    6. Arrays.fill(c, '.');
    7. }
    8. bakctrack(board,0);
    9. return res;
    10. }
    11. private void bakctrack(char[][] board, int row) {
    12. if(row==board.length){
    13. res.add(Array2List(board));
    14. return;
    15. }
    16. int n=board[0].length;
    17. for (int col = 0; col < n; col++) {
    18. //排除会发生冲突的格子
    19. if (!isValid(board,row,col)){
    20. continue;
    21. }
    22. //进行选择
    23. board[row][col]='Q';
    24. //进行下一行的放皇后
    25. bakctrack(board,row+1);
    26. //撤销选择
    27. board[row][col]='.';
    28. }
    29. }
    30. public List Array2List(char[][] chessboard) {
    31. List list = new ArrayList<>();
    32. for (char[] c : chessboard) {
    33. list.add(String.copyValueOf(c));
    34. }
    35. return list;
    36. }
    37. private boolean isValid(char[][] board, int row, int col) {
    38. int n=board.length;
    39. //检查列是否有冲突
    40. for (int i = 0; i < n; i++) {
    41. if (board[i][col]=='Q'){
    42. return false;
    43. }
    44. }
    45. for (int i = row-1,j=col+1; i >=0&&j
    46. if (board[i][j]=='Q'){
    47. return false;
    48. }
    49. }
    50. for (int i = row-1,j=col-1; i >=0&&j>=0; i--,j--) {
    51. if(board[i][j]=='Q'){
    52. return false;
    53. }
    54. }
    55. return true;
    56. }
    57. }

     

     

  • 相关阅读:
    微软正式发布开源应用平台 Radius平台
    parallelStream并行流性能
    HFish蜜罐实践:网络安全防御的主动出击
    css中设置元素大小的属性block-size
    关于ISP中各模块的调试顺序,及相互影响概述
    字典&文本特征提取,jieba库
    2022年起重机械指挥考试题及模拟考试
    触摸控件——增量调节
    MYSQL常用命令
    random—生成随机数,time—时间标准库
  • 原文地址:https://blog.csdn.net/qq_50985215/article/details/126025409