旅行售货员问题:某售货员要到若干城市去推销商品,已知各城市之间的路程(或旅费)。他要选定一条从驻地出发,经过每个城市一次,最后回到驻地的路线,使总的路程最短(或旅费最少)。
参考网址1(点这里)
参考网址2(点这里)
#include <iostream>
#include <string.h> //memset()
using namespace std;
const int maxNum = 1000; //定义一个最大值
const int NoEdge = -1; //两个点之间没有边
int citynum; //城市数
int edgenum; //边数
int currentcost; //记录当前的路程(花费)
int bestcost; //记录最小的路程(最优)
int Graph[100][100]; //图的边距记录
int x[100]; //记录行走顺序
int bestx[100]; //记录最优行走顺序
void InPut() //输入数据
{
int pos1, pos2, len; //点1 点2 距离
cout<<"请输入城市数和边数(citynum edgenum): ";
cin>>citynum>>edgenum;
memset(Graph, NoEdge, sizeof(Graph)); //初始状态所有点之间都没有边
//memset()函数原型是extern void *memset(void *buffer, int c, int count)
//buffer:为指针或是数组,c:是赋给buffer的值,count:是buffer的长度.
//作用是将某一块内存中的内容全部设置为指定的值, 这个函数通常为新申请的内存做初始化工作。
cout<<"请输入两座城市之间的距离(pos1 pos2 len):"<<endl;
for(int i = 1; i <= edgenum; i++)
{ //要注意pos的数值小于citynum
cin>>pos1>>pos2>>len;
Graph[pos1][pos2] = Graph[pos2][pos1] = len;
}
}
//初始化
void Initilize()
{
currentcost = 0; //当前路程:0
bestcost = maxNum; //最优路程
for(int i = 1; i <= citynum; i++) //每个城市的名称
{
x[i] = i;
}
}
void Swap(int &a, int &b)
{
int temp;
temp = a;
a = b;
b = temp;
}
void BackTrack(int i) //这里的i代表第i步去的城市而不是代号为i的城市 i:递归深度
{
if(i == citynum) //当前搜索的层级是处于排列树的叶节点的父节点上
{
//进行一系列判断,注意的是进入此步骤的层数应是叶子节点的父节点,而不是叶子节点
if(Graph[x[i - 1]][x[i]] != NoEdge && Graph[x[i]][x[1]] != NoEdge && (currentcost + Graph[x[i - 1]][x[i]] + Graph[x[i]][x[1]] < bestcost || bestcost == maxNum))
{
//最小(优)距离=当前的距离+当前城市到叶子城市的距离+叶子城市到初始城市的距离
bestcost = currentcost + Graph[x[i - 1]][x[i]] + Graph[x[i]][x[1]]; //更新当前最优值
for(int j = 1; j <= citynum; j++)
bestx[j] = x[j]; //更新当前最优解 即:最优=当前记录行走
}
}
else
{
for(int j = i; j <= citynum; j++)
{ // 检查x[i - 1]至x[i]之间是否存在一条边, 若存在,则x [1 : i ] 构成了图G的一条路径
if(Graph[x[i - 1]][x[j]] != NoEdge && (currentcost + Graph[x[i - 1]][x[j]] < bestcost || bestcost == maxNum))
{
Swap(x[i], x[j]); //择优排列 这里i 和 j的位置交换了, 所以下面的是currentcost += Graph[x[i - 1]][x[i]];
currentcost += Graph[x[i - 1]][x[i]];
BackTrack(i + 1); //递归进入下一个城市
currentcost -= Graph[x[i - 1]][x[i]];
Swap(x[i], x[j]); //回溯还原
}
}
}
}
void OutPut()
{
cout<<"最短路程为:"<<bestcost<<endl;
cout << "路线为:" << endl;
for(int i = 1; i <= citynum; i++)
cout << bestx[i] << " ";
cout << "1" << endl;
}
int main()
{
InPut();
Initilize();
BackTrack(2); //这里传递的是 第i步去的城市而不是代号为i的城市 i<=citynum
OutPut();
}