問題描述:
旅行商問題(Traveling Salesman Problem,TSP)是旅行商要到若干個城市旅行,各城市之間的費用是已知的,爲了節省費用,旅行商決定從所在城市出發,到每個城市旅行一次後返回初始城市,問他應選擇什麼樣的路線才能使所走的總費用最短?此問題可描述如下:設G=(V,E)是一個具有邊成本cij的有向圖,cij的定義如下,對於所有的i和j,cij>0,若<i,j>不屬於E,則cij=∞。令|V|=n,並假設n>1。 G的一條周遊路線是包含V中每個結點的一個有向環,周遊路線的成本是此路線上所有邊的成本和。
問題分析:
旅行商問題要從圖G的所有周遊路線中求取最小成本的周遊路線,而從初始點出發的周遊路線一共有(n-1)!條,即等於除初始結點外的n-1個結點的排列數,因此旅行商問題是一個排列問題。排列問題比子集合的選擇問題通常要難於求解得多,這是因爲n個物體有n!種排列,只有 個子集合(n!>O( ))。通過枚舉(n-1)!條周遊路線,從中找出一條具有最小成本的周遊路線的算法,其計算時間顯然爲O(n!)。
代碼如下(現在還有點問題,待會再改):#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#define MAX 1000
int* X = NULL;
bool NextValue(int k)
{
int i = 1;
while(i<k)
{
if(X[i] == X[k]) return false;
i++;
}
return true;
}
void TravelerProblem(int** w, int n)
{
int k;
int * temp = (int *)malloc((n+1)*sizeof(int));
X = temp;
int cl,fl;
for(int i=1;i<=n;i++)
X[i] =1;
k=2; cl=0; fl=MAX;
while(k>1)
{
X[k] = (X[k]+1)%n;
for(int j =0; j<n;j++)//分配狀態空間樹上的第k步爲哪一個節點
{
if(NextValue(k) == true)
{
cl = cl + w[X[k-1]][X[k]];
break;
}
X[k] = (X[k]+1)%n;
}
if((fl<= cl)||(k==n && fl<cl+w[X[k]][1])) //如果你現在選的這個節點已經使得fl<=cl或者已經全部選擇完畢了但仍然比先前的最短路徑長
{
cl-=w[X[k-1]][X[k]];
k-=1;
}
else if(k==n && fl>= cl+w[X[k]][1])
{
fl = cl + w[X[k]][1];
k-=1;
}
else k+=1;
}
}
void main()
{
puts("please input the counts of vertex:");
int n = 0;
scanf("%d", &n);
puts("please input the distance of two vertex:(1000 mean it is no edge between two vetex.)");
int** w = (int **)malloc((n+1)*sizeof(int *));
for(int i=1;i<=n;i++)
{
w[i] = (int *)malloc((n+1)*sizeof(int));
memset(w[i], 0, (n+1)*sizeof(int));
}
for(int i=1;i<=n;i++)
{
for(int j=1; j<=n;j++)
{
printf("the %dth row, %dth column value is:", i, j);
scanf("%d", &w[i][j]);
}
}
TravelerProblem(w, n);
return ;
}
問題:
1、知道怎樣定義動態的二維數組了;
2、這個算法的思想還是想不太明白;
3、回溯法啊回溯法,不懂啊~~~