回溯法理解,一般形式
void Bcktrack(int t) //参数t表示当前递归深度 { if(t>n)Output(x); //遍历到解,则将解输出或其他处理 else { //f(n,t)和g(n,t)表示当前节点(扩展节点)处未搜索过的子树的起始编号和中指编号 for(int i=f(n,t);i<=g(n,t);i++) { x[t]=h(i); //h(i)表示当前节点(扩展节点)处x[i]的第i个可选值 if(Constarint(t)&&Bound(t)) //剪枝函数:约束函数,限界函数 Bcktrack(t+1); } } }
例子一,八皇后问题
// MyEightQueen.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <VECTOR> #include <iostream> using namespace std; class EightQueen{ public: EightQueen(int n){ nqueen = n; solution.resize(nqueen + 1); numofsolutions = 0; } void put(){ _put(1); } int getnumofsolutions(){ return numofsolutions; } private: bool isplace(int n){ for(int i=1 ; i<n ; i++){ if(solution[i]==solution[n] || abs(n-i) == abs(solution[i] - solution[n])) return false; } return true; } void _put(int n){ if(n > nqueen){ //搜索到一个符合要求的解法 for(int i = 1;i<=nqueen;i++) cout<<solution[i]<<" "; cout<<endl; numofsolutions++; } else{ for(int j = 1;j<=nqueen;j++){ solution[n] = j; if(isplace(n)) //如果此处可以放置棋子,那么考虑放置下一个棋子,即_put(n+1) _put(n+1); } } } private: vector<int> solution; int nqueen; int numofsolutions; }; int main(int argc, char* argv[]) { EightQueen example(8); example.put(); cout<<"num of solutions "<<example.getnumofsolutions()<<endl; return 0; }
例子二:01背包问题
// 01Packet.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "stdio.h" int m,n=5,x[10]={0}; int w[6]={0,2,2,6,5,5},v[6]={0,6,3,5,4,6}; int c=10; int cw=0,cv=0,bestv=0; int f(int k) { int i; if (k>n) //已找到一个符合条件的解决方案 { for(i=1;i<=n;i++) printf("%d",x[i]); printf(" cv = %d",cv); if(cv>bestv) bestv=cv; printf("\n"); } else { for(int i = 0;i <= 1;i++){ x[k] = i; //H[i] = {0,1} int tempw = i*w[k] + cw; int tempv = i*v[k] + cv; if(tempw <= c){ //限制条件 cw = tempw; cv = tempv; f(k+1); //进行下一层处理 cw -= i*w[k]; //回溯之后将子路增加的和删除 cv -= i*v[k]; } } return k; } } int main(int argc,char * argv[]){ f(1); printf("bestv is %d\n",bestv); return 0; }