• 搜索回溯


    简介

    就是构建一颗搜索树,然后,基本上遍历所有的可能性然后找到结果,如果你想到暴力,那么你也应该想到递归回溯。

    使用的技术手段

    DFS, 递归, 回溯(说人话,就是在dfs的过程中,回退操作,进而对下一次的递归不造成影响)

    leetcode

    组合总和
    给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

    candidates 中的数字可以无限制重复被选取。

    说明:

    所有数字(包括 target)都是正整数。
    解集不能包含重复的组合。 
    示例 1:

    输入:candidates = [2,3,6,7], target = 7,
    所求解集为:
    [
    [7],
    [2,2,3]
    ]

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/combination-sum
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    题解

    #include <vector>
    #include <queue>
    #include <string>
    #include <algorithm>
    #include <string.h>
    using namespace std;
    #define ll long long
    #define mod (long long)(1e9+7)
    class Solution39 {
    public:
        void dfs(vector<int> &candidates, int target, vector<vector<int>> &ans, vector<int>& combine, int idx) {
            if(idx == candidates.size()) { // 如果走到的数组的末尾直接返回
                return;
            }
            if(target == 0) { // 如果我们需要
                ans.emplace_back(combine);
                return;
            }
            // 直接跳过
            dfs(candidates, target, ans, combine, idx + 1); // 一个数组对idx这个节点不进行选择,直接递归
            // 选择当前数
            if(target - candidates[idx] >= 0) {
                combine.emplace_back(candidates[idx]); // 选择这个节点,然后进行递归
                dfs(candidates, target - candidates[idx], ans, combine, idx);
                combine.pop_back(); // 为什么要进行pop_back操作,清除上一步的操作,上一步选择了这个节点,pop_back()清除这个操作
            }
        }
        vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
            vector<vector<int>> ans;
            vector<int> combine;
            dfs(candidates, target, ans, combine, 0);
            return ans;
        }
    };
    
    # 在递归回溯算法中最有名的解决方案应该就是对于8皇后的解决方案
    # 参考链接
    https://www.bilibili.com/video/BV1wJ411U7Gy?from=search&seid=2696729038749911359
    # 附上代码
    ```C++
    #include <iostream>
    using namespace std;
    int place[8]={0}; // 第n个皇后所占位置的列号
    bool flag[8] = {1, 1, 1, 1, 1, 1, 1, 1};// 标志数组,表示第col列是否可占用,1表示不冲突
    bool d1[15] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};// 表示上对角线是否可占
    bool d2[15] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};// 表示下对角线是否可占
    int number = 0; // 用于统计解的数量 八皇后共有92个解
    
    void print();
    void generate(int n);
    
    
    int main() {
        generate(0);
        return 0;
    }
    
    void generate(int n) {
        int col;
        for(col=0; col<8; col++){
            if(flag[col]&& d1[n-col+7] && d2[n+col]) {// 判断位置是否冲突
                place[n] = col;// 在n行col列摆放皇后
                flag[col] = false; // 宣布占领第col列
                d1[n-col+7] = false; // 宣布占领两个对角线
                d2[n+col] = false;
                if(n < 7) {
                    generate(n+1);
                }else{
                    print(); // N==7, 皇后都放完了,打印结果
                }
                // 回溯:考虑其他的可行方案
                flag[col] = true;
                d1[n - col + 7] = true;
                d2[n + col] = true;
            }
        }
    }
    
    void print() {
        int col, i, j;
        number++;
        printf("No. %d
    ", number);
        int table[8][8] = {0};
        for(i = 0; i<8; i++) {
            table[i][place[i]] = 1;
        }
        for(i = 0; i < 8 ; i++) {
            for(j = 0; j < 8; j ++) {
                printf("%d ", table[j][i]);
            }
            printf("
    ");
        }
    }
    
    Hope is a good thing,maybe the best of things,and no good thing ever dies.----------- Andy Dufresne
  • 相关阅读:
    [Java123] 方法重载中遇到的编译器错误: both methods have same erasure => 引入Java泛型type erasure
    [Java123] 认识JavaBean
    [Java123] HashMap实现和应用
    [Java123] 开源工具guava比较器链ComparisonChain (附加比较null空值的实现方法)
    [Java123] Java的异常处理机制
    [ORACLE123] sysdate处理
    Linux进程实时可视化监控
    【Java123】ThreadLocal学习笔记
    【XML123】了解XMLUnit
    字符串%s
  • 原文地址:https://www.cnblogs.com/eat-too-much/p/14565357.html
Copyright © 2020-2023  润新知