某售貨員要到若干城市去推銷商品,已知各城市之間的路程,他要選定一條從駐地出發,經過每個城市一遍,最後回到住地的路線,使總的路程最短。
結果為: 1 3 2 4 1
回溯法,序列樹, 假設起點為 1。
演算法開始時 x = [1, 2, 3, …, n]
x[1 : n]有兩重含義 x[1 : i]代表前 i 步按順序走過的城市, x[i + 1 : n]代表還未經過的城市。利用swap函式進行交換位置。
若當前搜尋的層次i = n 時,處在排列樹的葉節點的父節點上,此時演算法檢查圖g是否存在一條從頂點x[n-1] 到頂點x[n] 有一條邊,和從頂點x[n] 到頂點x[1] 也有一條邊。若這兩條邊都存在,則發現了乙個旅行售貨員的迴路(即:新旅行路線),演算法判斷這條迴路的費用是否優於已經找到的當前最優迴路的費用bestcost,若是,則更新當前最優值bestcost和當前最優解bestx。
若i < n 時,檢查x[i - 1]至x[i]之間是否存在一條邊, 若存在,則x [1 : i ] 構成了圖g的一條路徑,若路徑x[1: i] 的耗費小於當前最優解的耗費,則演算法進入排列樹下一層,否則剪掉相應的子樹。
//for迴圈結束後, 已搜尋遍當前擴充套件結點的所有未搜尋子樹.
}}採用樹的非遞迴深度優先遍歷演算法,可將回溯法表示為乙個非遞迴迭代過程。
void iterativebacktrack (
)//solution(t)為假,則僅得到乙個部分解,需繼續縱深搜尋
}else t--;}
//while迴圈結束後,完成整個回溯搜尋過程
}
子集樹通常有2n個葉結點, 遍歷子集樹的任何演算法均需ω(2n)的計算時間.
例如:0-1揹包問題的解空間為一棵子集樹.
排列樹通常有(n-1)!個葉結點, 遍歷排列樹需要ω(n!)的計算時間.
例如:旅行售貨員問題的解空間為一棵排列樹
.
const int max_ = 0x3f3f3f; //定義乙個最大值
const int noedge = -1; //兩個點之間沒有邊
int citynum; //城市數
int edgenum; //邊數
int currentcost; //記錄當前的路程
int bestcost; //記錄最小的路程(最優)
int graph[100][100]; //圖的邊距記錄
int x[100]; //記錄行走順序
int bestx[100]; //記錄最優行走順序
void input()
}//初始化
void initilize()
}void swap(int &a, int &b)
void backtrack(int i) //這裡的i代表第i步去的城市而不是代號為i的城市
}else}}
}void output()
{ cout<
以前面的樣例示範
輸入
請輸入城市數和邊數(c e):4 6
請輸入兩座城市之間的距離(p1 p2 l):
1 2 30
1 3 6
1 4 4
2 4 10
2 3 5
3 4 20
輸出
最短路程為:25
路線為:
回溯法 旅行售貨員問題
全排列回溯 include using namespace std const int max 0x3f3f3f 定義乙個最大值 const int noedge 1 兩個點之間沒有邊 int citynum 城市數 int edgenum 邊數 int currentcost 記錄當前的路程 in...
回溯法之旅行售貨員問題
問題描述 某售貨員要到若干城市去推銷商品,已知各城市之間的路程,他要選定一條從駐地出發,經過每個城市一遍,最後回到住地的路線,使總的路程最短。演算法描述 回溯法,序列樹,假設起點為 1。演算法開始時 x 1,2,3,n x 1 n 有兩重含義 x 1 i 代表前 i 步按順序走過的城市,x i 1 ...
分支限界法 旅行售貨員問題
一 問題描述 某售貨員要到若干城市去推銷商品,已知各城市之間的路程 或旅費 他要選定一條從駐地出發,經過每個城市一次,最後回到駐地的路線,使總的路程 或總旅費 最小。如下圖 1,2,3,4 四個城市及其路線費用圖,任意兩個城市之間不一定都有路可達。二 問題理解 1.分支限界法利用的是廣度優先搜尋和最...