回溯法之旅行商问题

问题描述:

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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章