回溯算法

来源:互联网 发布:乐清市网络问效平台 编辑:程序博客网 时间:2024/06/08 05:54

一,回溯算法的基本思想

回溯法从根节点出发,以深度优先搜素整个解空间。这个根节点成为活节点,成为当前的扩展节点。在当前扩展节点处,搜索向纵深方向移至一个新节点,这个新节点成为新的活节点,并成为当前扩展节点。如果在当前扩展节点处不能再向纵深方向移动,则当前扩展节点就成为死节点。此时,应往回移动至最近一个活节点处,并使这个活节点成为当前扩展节点。回溯法以这种工作方式递归地在解空间中搜索,直至找到所要求的解或解空间中已无活节点时为止。


二,子集树与排列树

子集树与排列数是用回溯法解问题时,常遇到的两种类型的解空间树。

1,子集树算法框架

void BackTrack(int i){    if(i >= n ){        //代码    }    if(c + w[i] <= load){        c += w[i];        x[i] = 1;        BackTrack(i + 1);        c -= w[i];    }    x[i] = 0;    BackTrack(i + 1);}
 

2,排列数算法框架

void BackTrack(int i){    if(i >= n ){        //代码    }    for(int j = i; j <n; j ++){        c += w[x[j]];        if(c > best){            Swap(i, j);            BackTrack(i + 1);            Swap(i, j);        }        c -= w[x[j]];    }}
 
三,常见的使用回溯法解决的问题

1,n后问题

class Queue{private:    int n;          //皇后数    int sum;        //当前找到的可行方案数    vector<int> x;  //存储当前解public:    Queue(int n):n(n){        sum = 0;        for(int i = 0; i <= n; i ++){            x.push_back(0);        }    }    bool isAttack(int i);    void BackTrack(int i);    int getSum();};/***  判断在第i层放置一个皇后之后,是否会与前面的皇后发生攻击,*  如果会发生攻击返回true,否则返回false*/bool Queue::isAttack(int i){    for(int j = 1; j < i; j ++){        if(x[j] == x[i] || abs(j - i) == abs(x[j] - x[i])){            return true;        }    }    return false;}void Queue::BackTrack(int i){    if(i > n){        sum ++;    } else {        for(int j = 1; j <= n; j ++){            //在第i行、第j列放置一个皇后            x[i] = j;            if(!isAttack(i)){                BackTrack(i + 1);            }        }    }}int Queue::getSum(){    BackTrack(1);    return sum;}


2,旅行商问题(排列树)

const int INF = 10000000;const int MaxSize = 20;class Traveling{private:    int n;                       //图中的顶点数    int c;                       //当前费用    int bestc;                   //当前最优费用    vector<int> x;               //当前解    vector<int> bestx;           //当前最优解    vector<vector<int> > e;      //图的邻接矩阵public:    Traveling(int a[][MaxSize], int n);    void BackTrack(int i);    void Swap(int i, int j);    int getBestc();};Traveling::Traveling(int a[][MaxSize], int n):n(n){    c = 0;    bestc = INF;    for(int i = 0; i < n; i ++){        x.push_back(i);        bestx.push_back(i);        vector<int> temp(n);        e.push_back(temp);    }    for(int i = 0; i < n; i ++){        for(int j = 0; j < n; j ++){            if(a[i][j] == -1){                e[i][j] = INF;            } else {                e[i][j] = a[i][j];            }        }    }}void Traveling::BackTrack(int i){    if(i >= n){        if(e[x[n -1]][x[0]] != INF && c + e[x[n -1]][x[0]] < bestc){            for(int j = 0; j < n; j ++){                bestx[j] = x[j];            }            bestc = c + e[x[n -1]][x[0]];        }        return;    }    for(int j = i; j < n; j ++){        if(i == 0){            Swap(i, j);            BackTrack(i + 1);            Swap(i, j);        } else {            if(e[x[i - 1]][x[j]] != INF && c + e[x[i - 1]][x[j]]< bestc){                Swap(i, j);                c += e[x[i - 1]][x[i]];                BackTrack(i + 1);                c -= e[x[i - 1]][x[i]];                Swap(i, j);            }        }    }}void Traveling::Swap(int i, int j){    int temp = x[i];    x[i] = x[j];    x[j] = temp;}int Traveling::getBestc(){    BackTrack(0);    return bestc;}

原创粉丝点击