回溯之子集树和排列树

  再总结下回溯法,回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法。基本思想:在包含问题的所有解的解空间树中,按照深度优先搜索的策略,从根结点出发深度探索解空间树。当探索到某一结点时,要先判断该结点是否包含问题的解,如果包含,就从该结点出发继续探索下去,如果该结点不包含问题的解,则逐层向其祖先结点回溯。若用回溯法求问题的所有解时,要回溯到根,且根结点的所有可行的子树都要已被搜索遍才结束。 而若使用回溯法求任一个解时,只要搜索到问题的一个解就可以结束。回溯法解题的时候常遇到两种类型的解空间树:子集树(选择问题)与排列树(排列问题)。当所给的问题是从n个元素的集合S中找出满足某种性质的子集时相应的空间就是子集树。当所给的问题是确定n个元素满足某种性质的排列时,相应的解空间树就是排列树。

子集树(选择问题)的一个例子:

#include <iostream>
using std::cin;
using std::cout;
using std::endl;
class Partsum {
public:
    int S = 30;
    int num = 0;
    int x[7] = { 0 };
    int w[7] = { 0,5,10,12,13,15,18 };
    //回溯,sum为当前和,k为层数,r为剩余数的和
    void Backtrack(int sum, int k, int r) {
        if (sum + w[k] == S) {
            num++;
            cout << num << ":";
            cout << "S = ";
            for (int i = 1; i <= k; i++) {
                if (x[i] == 1) {
                    cout << w[i] << "+";
                }
                else {
                    continue;
                }
            }
            cout << w[k] << endl;
        }
        //到下一层sum小于S,则进入左子树
        if (sum + w[k] + w[k + 1] <= S) {
            x[k] = 1;
            Backtrack(sum + w[k], k + 1, r - w[k]);
        }
        //剪掉当前值,小于S则不可能是右子树了
        if (sum + r - w[k] >= S) {
            x[k] = 0;
            Backtrack(sum, k + 1, r - w[k]);
        }
    }
};
int main(int argc, char* argv[]) {
    Partsum p;
    p.Backtrack(0, 1, 73);
    return 0;
}

排列数(排列问题)的一个例子:

#include <iostream>
using std::cin;
using std::cout;
using std::endl;
class Arranage {
public:
    float A[4] = { 0,1,2 };
    void arrage(int k, int m) {
        int i, temp;
        if (k == m) {
            for (i = 0; i <= m; i++) {
                cout << A[i] << " ";
            }
            cout << endl;
        }
        else {
            for (i = k; i <= m; i++) {
                swap(A[k], A[i]);
                arrage(k + 1, m);
                swap(A[i], A[k]);
            }
        }
    }
    template<class Type>
    void swap(Type &x, Type &y) {
        Type temp;
        temp = x;
        x = y;
        y = temp;
    }
};
int main(int argc, char* argv[]) {
    Arranage arr;
    arr.arrage(0, 2);
    return 0;
}

 

猜你喜欢

转载自www.cnblogs.com/SHNLQS-1273196803/p/11061218.html
今日推荐