问题描述:
旅行商问题(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、回溯法啊回溯法,不懂啊~~~