您的位置:首页 > 其它

【算法设计与分析基础】蛮力法解决旅行商问题

2016-10-15 00:14 176 查看
        蛮力法解题思想:旅行商问题(又叫货郎担问题)可以表述为求一个最短的哈密顿回路问题。因为是回路,所以可以假设所有的回路都起点和终点都为同一个点,从而生成n-1个中间城市的排列。通过递归函数遍历所有城市,并记录每一种排列所得路径的长度,比较后得到最短路径。

   


  对于上图所示的图,很显然最短的回路为:a→b→d→c→a;

   首先我们选择a为出发点,遍历以a为起点/终点的所有可能的路径,并记录其长度;

   再以b为出发点,遍历以b为起点/终点的所有可能的路径,并记录其长度;

   ......

   那么如何实现呢?

   

    这里我选择的是vc6.0。

    首先我们需要写一个函数(在java中叫方法),生成n个结点的图的所有结点排列的全排列数量;    

int jiecheng(int n)//n的阶乘
{
int s = 1;
for(int i = 1;i <= n; i++)
s=s*i;
return s;
}
     知道了全排列的数量,就要去实现全排列,那么怎么是实现呢?

     abcd,abdc,adbc....

     知道规律了吗?

     交换两个结点的顺序就是一个排列,所以缺少一个swap函数:  

void swap(int &a, int &b)//交换两个数
{
int temp;
temp = a;
a = b;
b = temp;
}
      接下来就是生成全排列:

//求从n取m个数的排列
//A[]为等待求组合的数组,长度为n,同时用来保存结果
//start挑选的起点
//step步数
//Max全排列的数目
//dist[][]为距离矩阵
//path[]为路径
void Arrange(int A[],int start,int step,int n,int m,int Max,int *path,int **dist)
{
if(n < m)	m = n;//从n个数中最多可以求n个数的全排列

if (step == m)//穷举求最小的路径并存到数组中
{
len=0;
count++;
for (int i = 0;i < m; i++)//计算当前序列的路径长度
{
if(i < m-1)//
len = len+dist[A[i]][A[i+1]];
else
len = len+dist[A[i]][A[0]];
cout<<A[i]<<" ";
}
if(len < mindist)//更新最短路径
{
mindist = len;
for(i = 0;i < m; i++)
path[i] = A[i];
path[i] = A[0];
}
cout<<endl;
}
if(count == Max)//做完之后输出最短路径及其长度
{
cout<<"最短路径为:"<<mindist<<endl;
cout<<"旅行路线为:";

for(int i = 0;i <= m; i++)
{
char name [4] = {'a','b','c','d'};
if(i != 0 && path[i] == 0)//终点
cout<<" ("<<name[path[i]]<<")";
else//非终点
cout<<" ("<<name[path[i]]<<") "<<"--"<<dist[path[i]][path[i+1]]<<"-->";
}
cout<<endl;
}
else
{
//第j个数分别与它后面的数字交换就能得到新的排列

for (int j = start; j < n; j++)
{
swap(A[step],A[j]);
Arrange(A,start+1,step+1,n,m,Max,path,dist);
swap(A[j],A[step]);
}
}
}


     然后再写函数去调用它们;

//城市个数n,距离矩阵dist[][]
//旅行路线path,最小距离min
void solution(int n,int **dist,int *path)
{
int Max = jiecheng(n);	//全排列的数目,算法的时间复杂度
int *Array = new int
;

for(int i = 0;i < n; i++)//初始化序列(顺序)
Array[i] = i;

Arrange(Array,0,0,n,n,Max,path,dist);
}


最后是main函数

void main()
{
int N = 4;
cout<<"城市个数:"<<endl<<N<<endl;

int *path = new int[N+1];	//存贮最优路径
int **Graph = new int *
;	//建立动态的距离矩阵;

for(int i = 0;i < N; i++)
Graph[i] = new int
;

ifstream input;
input.open("1.txt"); //从txt文档读入矩阵信息

for(i = 0;i < N; i++)
for(int j = 0;j < N; j++)
input>>Graph[i][j]; //从txt文档输入矩阵

cout<<"距离矩阵:"<<endl;
for(i = 0;i < N; i++)
{
for(int j = 0;j < N; j++)
cout<<Graph[i][j]<<" ";

cout<<endl;
}
cout<<"求得所有排列如下:"<<endl;
solution(N,Graph,path);
}


其中1.txt为:

0 2 5 7
2 0 8 3
5 7 0 2
7 3 2 0

对于上图,输出的结果为:



   
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: