回溯法之旅行商問題

問題描述:

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


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