旅行商问题(TSP)
旅行商问题是一个经典的组合优化问题。
经典的TSP问题可以描述为:一个商品推销员要去若干个城市进行商品推销,该推销员从一个城市出发,需要经过所有城市,回到出发地。应如何选择行进路线,以使总的行程最短。
从图论的角度来看,该问题实质是在一个带权完全无向图中,找一个权值最小的Hamilton回路。
由于该问题的可行解是所有顶点的全排列,随着顶点数的增加,会产生组合爆炸。
在这里我们以贪心算法来解决这个问题,当数据规模越大时,以近似解来替代最优解。
#include <iostream>
#include <assert.h>
using namespace std;
#define MAX 1000000
#define n 4
int D[n][n]; //记录两城市间距离
int S[n]; //记录第i次去的城市
void Init()
{
for (int i = 0; i < n; ++i)
for (int j = i; j < n; ++j)
D[i][j] = D[j][i] = MAX;
for (int i = 0; i < n; ++i)
S[i] = -1;
}
bool checkAccess(int city)
{
//判断该城市是否访问过
for (int i = 0; i < n; ++i)
if (S[i] == city)
return true;
return false;
}
int findCity(int city)
{
//查找下一次要去的距离最短的城市
int min = MAX;
int nextCity;
for (int i = 0; i < n; ++i)
if (D[city][i] < min && checkAccess(i) == false)
{
min = D[city][i];
nextCity = i;
}
return nextCity;
}
void TSP(int start)
{
S[0] = start;
size_t sum = 0;
for (int i = 1; i < n; ++i)
{
S[i] = findCity(S[i - 1]);
sum += D[S[i - 1]][S[i]];
}
printf("访问顺序为:");
for (int i = 0; i < n; ++i)
printf("%d", S[i]);
printf("\n");
printf("总距离为:%d", sum);
}
int main()
{
int i, j, k;
Init(); //初始化距离数组和访问数组
/*while (scanf("%d%d%d",&i,&j,&k) != EOF) { assert(i >= 0 && j >= 0 && k > 0 && i != j); D[i][j] = D[j][i] = k; }*/
D[0][1] = D[1][0] = 2;
D[0][2] = D[2][0] = 6;
D[0][3] = D[3][0] = 5;
D[1][2] = D[2][1] = 4;
D[1][3] = D[3][1] = 4;
D[2][3] = D[3][2] = 2;
TSP(0);
getchar();
return 0;
}