回朔算法

回朔算法的思想很簡單,每一步都是嘗試,如果正確進行下一步,如果不正確則回退,回退到上一步或者原點。 爲了優化時間,不必要的搜索要進行剪枝操作

常見的深度優先搜索就是回朔法的思想,來幾道經典的回朔法。

1.https://leetcode-cn.com/problems/combination-sum/    代碼有註釋,今天時間緊急,後邊有時間畫圖放上邊加以理解

class Solution {
public:
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        vector<vector<int>> res;
        vector<int> tmp;
        sort(candidates.begin(), candidates.end());   //排序,也是爲了剪枝
        int len = candidates.size();
        combinationSumCore(res, candidates, target, tmp, 0, 0, len);
        return res;
    }
    void combinationSumCore(vector<vector<int>> &res, vector<int>& candidates, int target, vector<int>& tmp, int sum, int begin, int len){
        if(sum == target)    //如果sum等於目標值 則將tmp的vector放到res中
            res.push_back(tmp);
        else
        {
            for(int i = begin; i < len; i++)
            {
                if(candidates[i] + sum <= target)
                {
                    tmp.push_back(candidates[i]);
                    combinationSumCore(res, candidates, target, tmp, candidates[i] + sum, i, len);   //可以被無限重複的選,則i還是原來的座標
                    tmp.pop_back();    //回朔,一步一步回到 符合要求的一步  或者 返回到第一層i = begin  這一步
                }
                else      //剪枝操作
                    break;
            }
        }
    }
};

2.https://leetcode-cn.com/problems/combination-sum-ii/

class Solution {
public:
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) 
    {
        vector<vector<int>> res;
        vector<int> tmp;
        sort(candidates.begin(), candidates.end());
        int len = candidates.size();
        combinationSumCore(res, candidates, target, tmp, 0, 0);
        return res;
    }
    
     void combinationSumCore(vector<vector<int>> &res, vector<int>& candidates, int target, vector<int>& tmp, int sum, int begin){
        if(sum == target){
            res.push_back(tmp);
        }
        else
        {
            for(int i=begin; i<candidates.size(); ++i)    //整個一輪返回來,當i = 1, 就會去重複了  稍微有點繞
            {
                if(sum+candidates[i]<=target)
                {
                    if(i != begin && candidates[i] == candidates[i-1])  //去重複    //整個一輪返回來,當i = 1, 就會去重複了  稍微有點繞
                        continue;
                    tmp.push_back(candidates[i]);
                    combinationSumCore(res, candidates, target, tmp, sum+candidates[i], i + 1);
                    tmp.pop_back();     //一層一層返回,一直到第一層 i = begin + 1;
                }
                else
                    break;
            }
        }
    }
};

3.https://leetcode-cn.com/problems/word-search/

class Solution {
public:
    int n, m;
    int dx[4] = {-1, 0, 1, 0};
    int dy[4] = {0, 1, 0, -1};
    bool exist(vector<vector<char>>& board, string word) 
    {
        if(board.empty() || board[0].empty()) 
            return false;
        n = board.size(), m = board[0].size();
        for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < m; j++)
            {
                if(dfs(board, word, i, j, 0))      //false  就繼續試下一個點
                    return true;
            }
        }
        return false;
    }
    
    bool dfs(vector<vector<char>>& board, string& word, int x, int y, int u)
    {
        if(board[x][y] != word[u])
            return false;
        if(u == word.size() - 1)
            return true;
        board[x][y] = '.';          //不能繼續探索到當前點,只有三個方向
        for(int i = 0; i < 4; i++)
        {
            int a = x + dx[i];
            int b = y + dy[i];
            if(a >= 0 && a < n && b >= 0 && b < m)        //判斷下一個探索的點是否合法
                if(dfs(board, word, a, b, u+1))
                    return true;
        }
        board[x][y] = word[u];        //回朔,回到這個點
        return false;    
    }
};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章