旅行商问题(深度优先搜索 回溯法 排列树)

来源:互联网 发布:2016年1月非农数据 编辑:程序博客网 时间:2024/04/30 02:58

1.问题描述:

有一个推销员,要到n个城市推销商品,他要找出一个包含所有n个城市的具有最短路程的环路。(最后回到原来的城市)

示例:从城市1出发经过所有城市后回到城市1,要使总路程最短。

2.算法设计:

给定n个城市的无向带权图G(V,E),顶点代表城市,权值代表城市之间的距离。若城市之间没有路径,则距离为无穷。

城市之间的距离存放在二维数组g[][]中。

从城市1出发,先到临近城市2,将走过的路程存放在变量 cl 中。

bestl代表当前找到的一种最短路径长度。如走法:1-2-3-4-5-1

显然,向城市深处走时,cl只会增加。因此当cl>bestl时,不必再往深处走。

限界条件为cl<bestl, cl 初值为0,bestf初值为∞

3.代码:

#include<iostream>using namespace std;#define MAX 1000int g[100][100],x[100],bestx[100];int cl=0,bestl=MAX,n;void Traveling(int t){    int j;    if(t>n) //到达叶子结点    {        if(g[x[n]][1]!=-1 && (cl+g[x[n]][1]<bestl))//推销员到的最后一个城市与出发的城市之间有路径,且当前总距离比当前最优值小        {            for(j=1; j<=n; j++)                bestx[j]=x[j];            bestl=cl+g[x[n]][1];        }    }    else    //没有到达叶子结点    {        for(j=t; j<=n; j++)//搜索扩展结点的左右分支,即所有与当前所在城市临近的城市        {            if(g[x[t-1]][x[j]]!=-1 && (cl+g[x[t-1]][x[j]]<bestl))//若果第t-1个城市与第t个城市之间有路径且可以得到更短的路线            {                swap(x[t],x[j]);     //保存要去的第t个城市到x[t]中                cl+=g[x[t-1]][x[t]]; //路线长度增加                Traveling(t+1);      //搜索下一个城市                cl-=g[x[t-1]][x[t]];                swap(x[t],x[j]);            }        }    }}int main(){    int i,j;    cout<<"请输入一共有几个城市:"<<endl;    cin>>n;    cout<<"请输入城市之间的距离"<<endl;    for(i=1; i<=n; i++)        for(j=1; j<=n; j++)            cin>>g[i][j];    for(i=1; i<=n; i++)    {        x[i]=i;        bestx[i]=0;    }    Traveling(2);    cout<<"城市路线:"<<endl;    for(i=1; i<=n; i++)        cout<<bestx[i]<<' ';        cout<<bestx[1];    cout<<endl;    cout<<"最短路线长度:"<<endl;    cout<<bestl<<endl;    return 0;}/*测试数据:5-1 10 -1 4 1210 -1 15 8 5-1 15 -1 7 30 4 8  7 -1 612 5 30  6 -1*/



1 1