貪心演算法解決tsp問題
阿新 • • 發佈:2018-12-27
簡介完了,說下思路. 就是不考慮遠方,只考慮下一步, "今朝有酒今朝醉" , 只有保證下一步是最近的距離即可 .
要找到最近的下一步,首先需要把已經出現過的城市排除 ,
s[]記錄了訪問過的城市列表,遍歷這個列表,訪問過返回YES,沒訪問返回NO.
以上就是核心程式碼了, 當時學習的時候,把3個迴圈巢狀寫在一個函式裡了 , 看得一臉懵逼, 將其拆成3個函式後 , 思路瞬間清晰多了 , 執行完之後s[]中就存放了所有的結果,遍歷列印就是訪問順序了. 下面是全部程式碼 , 可以複製貼上執行試試,哦還有這是那個示意圖
最後執行結果
// 這個城市k是否出現過了
bool isShowed(int k) {
for (int i = 0; i < cityNum ; i++) {
if (s[i] == k) {
return YES ;
}
}
return NO;
}
找了未訪問的城市,還需要找出這些未訪問城市中最短的距離.
distance是一個二維陣列,存放了 i, j 城市間的距離, distance[i][s[currentCity]] 表示第i個城市
和 當前訪問城市間的距離 .i 不斷增加,遍歷了所有的城市,就可以找到最短距離了.void clostCityDistance(int currentCity) {
// 距離當前城市最近的下一個城市
int tempClosest = 9999;
for (int i = 0; i < cityNum; i++) {
if ( isShowed(i) == NO && distance[i][s[currentCity]] <tempClosest ) {
tempClosest = distance[i][s[currentCity]] ;
s[currentCity+1] = i ;
}
} // 判斷是否應該結束了, 如果s[]中有一個還是初始值-1的話,說明不該結束,繼續尋找下一個城市. bool shouldFinish = YES; for (int i = 0; i < cityNum; i++) { if ( s[i] == -1 ) { shouldFinish = NO ; } } if (shouldFinish == NO) { clostCityDistance(s[currentCity+1]); } else { return ; } }
// 剩下就是初始條件了, 初始化出發的城市,可以是0,1,2,3任意一個
s[0] = 0; // s[0] = 1 ;
clostCityDistance(s[0]) ;
以上就是核心程式碼了, 當時學習的時候,把3個迴圈巢狀寫在一個函式裡了 , 看得一臉懵逼, 將其拆成3個函式後 , 思路瞬間清晰多了 , 執行完之後s[]中就存放了所有的結果,遍歷列印就是訪問順序了. 下面是全部程式碼 , 可以複製貼上執行試試,哦還有這是那個示意圖
#define cityNum 4 // 已訪問過的城市記錄陣列, 初始化為-1,表示未訪問 int s[cityNum] = {-1,-1,-1,-1} ; // 城市間距離陣列,999表示自己到自己的距離,隨意寫的 int distance[cityNum][cityNum] = {{999,2,6,5}, {2,999,5,4}, {6,5,999,2}, {5,4,2,999} }; // 這個城市是否出現過了 bool isShowed(int k) { for (int i = 0; i < cityNum ; i++) { if (s[i] == k) { return YES ; } } return NO; } // 距離當前城市最近的下一個城市 void clostCityDistance(int currentCity) { int tempClosest = 9999; for (int i = 0; i < cityNum; i++) { // 此處判斷是取 < ,也就是說 b->c, b->d間距離相同的話,使用b->c作為最優解, // 繼續深入思考,其實b->c和b->d是一樣的話,應該同時考慮,那麼就不應該用for迴圈了,感覺用遞迴更好,
//可以考慮任意深度的相等,直到某一條路徑勝出,可惜只是想法,具體實現不太會....
if ( isShowed(i) == NO && distance[i][s[currentCity]] <tempClosest ) {
tempClosest = distance[i][s[currentCity]] ;
s[currentCity+1] = i ;
}
}
// 找出了當前的最短路徑,還要判斷是否應該結束
bool shouldFinish = YES;
for (int i = 0; i < cityNum; i++) {
if ( s[i] == -1 ) {
shouldFinish = NO ;
}
}
if (shouldFinish == NO) {
clostCityDistance(s[currentCity+1]); // 不該結束,那就繼續尋找
} else {
return ;
}
}
void tspQuestion() {
// 初始化出發的城市,可以是0,1,2,3任意一個
s[0] = 0;
clostCityDistance(s[0]) ;
// 為了輸出 最短路徑,並求最短路徑之和
int allDistance = 0 ;
for (int i=0; i < cityNum ; i++) {
if (i == cityNum -1) {
printf("本次訪問的城市%d ",s[i] );
printf("回到原點%d距離是%d\n",s[0],distance [ s[cityNum-1] ] [s[0]]);
printf("總距離是 %d\n",allDistance += distance [ s[cityNum-1] ] [s[0]] );
break ;
}
printf("本次訪問的城市%d 距離下一個%d城市%d\n",s[i],s[i+1], distance[ s[i] ][ s[i+1] ] );
allDistance += distance[ s[i] ][ s[i+1] ] ;
}
}
int main(int argc, const char * argv[]) {
// tsp 問題
tspQuestion() ;
}
最後執行結果
本次訪問的城市0 距離下一個1城市2
本次訪問的城市1 距離下一個3城市4
本次訪問的城市3 距離下一個2城市2
本次訪問的城市2 回到原點0距離是6
總距離是 14