問題描述:
旅行商問題(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 1000int* 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、回溯法啊回溯法,不懂啊~~~