回溯算法
来源:互联网 发布:乐清市网络问效平台 编辑:程序博客网 时间: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;}
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;}