标签:
1. 回溯法的基本原理: 回溯算法也叫试探法,它是一种系统地搜索问题的解的方法。回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试。用回溯算法解决问题的一般步骤为: 1、定义一个解空间,它包含问题的解。 2、利用适于搜索的方法组织解空间。 3、利用深度优先法搜索解空间。 4、利用限界函数避免移动到不可能产生解的子空间。 问题的解空间通常是在搜索问题的解的过程中动态产生的,这是回溯算法的一个重要特性。 2.旅行售货员问题的回溯算法实现 算法具体实现主要代码如下: // TravelSaler.cpp : 定义控制台应用程序的入口点。 // //旅行员售货员问题 回溯法求解 #include "stdafx.h" #include <iostream> #include <fstream> #include<stdlib.h> using namespace std; ? ifstream fin("input.txt"); const int N = 4;//图的顶点数 ? template<class Type> class Traveling { ????template<class Type> ????friend Type TSP(Type **a, int n); private: ????void Backtrack(int i); ????int n,???????? // 图G的顶点数 ????????*x, // 当前解 ????????*bestx; // 当前最优解 ????Type **a, // 图G的领接矩阵 ????????cc, // 当前费用 ????????bestc; // 当前最优值 ????int NoEdge; // 无边标记 }; ? template <class Type> inline void Swap(Type &a, Type &b); ? template<class Type> Type TSP(Type **a, int n); ? int main() { ????cout << "图的顶点个数 n=" << N << endl; ? ????int **a = new int*[N + 1]; ????for (int i = 0; i <= N; i++) ????{ ????????a[i] = new int[N + 1]; ????} ? ????cout << "图的邻接矩阵为:" << endl; ? ????for (int i = 1; i <= N; i++) ????{ ????????for (int j = 1; j <= N; j++) ????????{ ????????????fin >> a[i][j]; ????????????cout << a[i][j] << " "; ????????} ????????cout << endl; ????} ????cout << "最短回路的长为:" << TSP(a, N) << endl; ? ????for (int i = 0; i <= N; i++) ????{ ????????delete[]a[i]; ????} ????delete[]a; ? ????a = 0; ????system("pause"); ????return 0; ???? } ? template<class Type> void Traveling<Type>::Backtrack(int i) { ????if (i == n) ????{ ????????if (a[x[n - 1]][x[n]] != 0 && a[x[n]][1] != 0 && ????????????(cc + a[x[n - 1]][x[n]] + a[x[n]][1] < bestc || bestc == 0)) ????????{ ????????????for (int j = 1; j <= n; j++) bestx[j] = x[j]; ????????????bestc = cc + a[x[n - 1]][x[n]] + a[x[n]][1]; ????????} ????} ????else ????{ ????????for (int j = i; j <= n; j++) ????????{ ????????????// 是否可进入x[j]子树? ????????????if (a[x[i - 1]][x[j]] != 0 && (cc + a[x[i - 1]][x[i]] < bestc || bestc == 0)) ????????????{ ????????????????// 搜索子树 ????????????????Swap(x[i], x[j]); ????????????????cc += a[x[i - 1]][x[i]]; //当前费用累加 ????????????????Backtrack(i + 1);????????????//排列向右扩展,排列树向下一层扩展 ????????????????cc -= a[x[i - 1]][x[i]]; ????????????????Swap(x[i], x[j]); ????????????} ????????} ????} } ? template<class Type> Type TSP(Type **a, int n) { ????Traveling<Type> Y; ????Y.n = n; ????Y.x = new int[n + 1]; ????Y.bestx = new int[n + 1]; ? ????for (int i = 1; i <= n; i++) ????{ ????????Y.x[i] = i; ????} ? ????Y.a = a; ????Y.cc = 0; ????Y.bestc = 0; ? ????Y.NoEdge = 0; ????Y.Backtrack(2); ? ????cout << "最短回路为:" << endl; ????for (int i = 1; i <= n; i++) ????{ ????????cout << Y.bestx[i] << " --> "; ????} ????cout << Y.bestx[1] << endl; ? ????delete[] Y.x; ????Y.x = 0; ????delete[] Y.bestx; ? ????Y.bestx = 0; ????return Y.bestc; } ? template <class Type> inline void Swap(Type &a, Type &b) { ????Type temp = a; ????a = b; ????b = temp; } 其中input.txt的内容为: 0 30 6 4 30 0 5 10 6 5 0 20 4 10 20 0 |
编译并运行程序。 3. 旅行售货员问题的回溯算法的解空间树以及搜索过程:
(3)算法的时间复杂性和空间复杂性 ?算法backtrack在最坏情况下可能需要更新当前最优解O((n-1)!)次,每次更新bestx需计算时间O(n),从而整个算法的计算时间复杂性为O(n!)。? |
程序运行结果如下:
? 开始测试时每次都要输入图的邻接矩阵,非常麻烦,后面改为直接从input文件中读取,大大简化了调试过程 |
标签:
原文地址:http://www.cnblogs.com/leftshine/p/5698557.html