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文件中讀取,大大簡化了調試過程 |