演算法學習1:旅行售貨員問題
有一推銷員,欲到n <=10個城市推銷產品。為了節省旅行費用,在出發前他查清了任意兩個城市間的旅行費用,想找到一條旅行路線,僅經過每個城市一次,最終回到出發原點,使旅行費用最少。本問題已知城市n,和n*n的表達任意兩個城市間費用的矩陣。求最短路徑及其費用。
這裡假設起點不限,從任意起點出發均可。
問題的抽象即為求解一個圖的最小漢密爾頓迴路。從一個點出發,不重複地走遍圖中的所有點,即得到一條漢密爾頓迴路。此題求解問題的最優解,考慮到問題的規模比較小,可以使用暴力法得到所有解。因為要求不重不漏,問題就轉化為求陣列全排列。可用遞歸回溯求全排列。篩選出選定的起點,然後依次算其迴路成本,最終選出最優解。
#include <stdio.h>
int Ham_Path[10],min_cost=1000000,cost = 0; //Ham_Path always remember the best path
int Matrix[10][10];
int n = 0;
void swap(int *a, int *b)
{
int m;
m = *a;
*a = *b;
*b = m;
}
void perm(int path[], int k, int m)
{
int i;
if(k > m)
{
if(path[0]==0) //choose the point '0' as the first point
{
path[m+1] = 0;
for(int k=0; k<=m; k++)
{
cost=cost+Matrix[path[k]][path[k+1]];
}
if(cost<min_cost)
{
min_cost=cost;
for(i = 0; i <= m; i++)
{
Ham_Path[i]=path[i];
}
}
}
}
else
{
for(i = k; i <= m; i++)
{
swap(&path[k], &path[i]);
perm(path, k + 1, m);
swap(&path[k], &path[i]);
}
}
}
int main()
{
int CityNum;
int path[20];
for(int i=0; i<20; i++)
{
path[i]=i;
}
//printf("total:%d\n", n);
scanf("%d",&CityNum);
printf("Please input the number of the cities\n");
for(int i=0; i<CityNum; i++) //the matrix is the cost from one city to another
{
for(int j=0; j<CityNum; j++)
{
scanf("%d",&Matrix[i][j]);
}
}
perm(path, 0, CityNum-1);
for(int i = 0; i < CityNum; i++)
{
printf("%d->",Ham_Path[i]);
}
printf("%d least cost:%d\n",Ham_Path[CityNum],min_cost);
return 0;
}