標籤:
TSP問題一直是個頭疼的問題,但是解決的方法數不勝數,很多的演算法也都能解決。百度資料一大堆,但是我找到了代碼比較簡練的一種。隨機法。下面只是個人的看法而已,如果有任何問題虛心接受。
顧名思義,隨機法就是隨機一個序列然後用這個序列去解決問題。
TSP問題描述中,一個人走一圈回到原點要使走過的路程最短,那麼他一定有一個路徑,隨機法,隨機的就是這個路徑。
首先我們要明白的是,只要隨機的量足夠大,最終一定能得到結果,因為能隨機到枚舉的全部。
第二,隨機了一個路徑之後,我們要在這個路徑下面找到最短的路徑,方法是通過交換兩個位置得到的。
第三,要根據題目意思,確定圖不是很大,或者資料量並非那種特別巨大的題目,也就是說看清題目。靈活選用方法。
1、我們隨機一個路線出來
0-3-1-2-0(最終是要返回0的)
2、我們根據這個路徑找到這個路徑的路程s。
3、除了首尾的0之外,交換任意兩個數,如果交換完了之後s變小了,就更新s
聽上去是不是覺得這個演算法很扯,是不是感覺最終得不到最優解,可是當你迴圈個50000次試試,你就知道,基本上99%都能拿到最優解,這個比暴力搜尋快,但是比dp不穩,這個演算法的有點在於編碼不複雜,而且在基本問題上面都能得到最優解,所以最終我選擇了這個。
下面附上代碼:
#include<cstdio>#include<cstdlib>#include<iostream>#include<algorithm>using namespace std;/*TSP隨機法*/int n;//圖的大小int maps[20][20];//記錄任意兩點的距離int order[20];//記錄行走的順序//計算當前行走順序下的距離int dis(){ int nowDis=0; int i; //因為是從0開始走最後返回所以是n+1 for (i = 1; i <= n+1; i++) { nowDis += maps[order[i-1]][order[i]]; } return nowDis;}int main(){ int i,j; int answer;//記錄答案 int result;//記錄最終輸出 int ready=0;//記錄是否成功 int temp;//臨時變數 cin>>n; //使用者輸入家到任意一點的距離,儲存在第一行中 for (i = 1; i <= n; i++) { cin>>maps[0][i]; maps[i][0] = maps[0][i]; } //使用者輸入任意兩點間的距離 for (i = 1; i <= n; i++) { for (j = 1; j <= n; j++) { cin>>maps[i][j]; maps[j][i] = maps[i][j]; } } result = 999999999; //下面是隨機開始 int t;//隨機的次數 for (t = 0; t < 50000; t++) { //初始化隨機序列 for (i = 1; i <= n; i++) order[i] = i; order[0] = 0;//一定是從0點開始走 order[n+1] = 0;//一定最終回到0點 //交換任意隨機序列中的值,不動0點和n+1點的值 for (i = 1; i <= n; i++) { j = rand()%n + 1; swap(order[i],order[j]); } //擷取當前最短路 answer = dis(); while (true) { ready = 0; for (i = 1; i <= n; i++) { for (j = i+1; j <= n; j++) { //交換每兩個值 swap(order[i],order[j]); temp = dis(); //如果當前交換之後,比當前路徑小,那麼就更新值 if(temp < answer) { answer = temp; ready = 1; } else//如果不比當前小,交換回來 swap(order[i],order[j]); } } //只要有一次交換,那麼就再一次迴圈,確保不存在更小的路徑 if(ready == 0) break; } if(result > answer) result = answer; } cout<<result<<endl; return 0;}
隨機法解決TSP問題