TSP 算法给出不正确的输出
Algorithm for TSP giving incorrect output
我花了几个小时试图找出我的程序有什么问题,但我无法弄清楚。这是一个最低旅游成本的项目。 (TSP)
c 代表城市,a 代表弧形(2 个城市之间的旅行费用)
我用来测试的输入:
c 1
c 2
c 3
c 4
c 5
a 1 2 1400
a 1 3 1800
a 1 4 4000
a 1 5 3500
a 2 3 1200
a 2 4 3400
a 2 5 3600
a 3 4 2300
a 3 5 2700
a 4 5 2100
这是我的代码。上面的输入应该给出 10500 minTour,但它显示 5600。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cassert>
#include <sstream>
#include <cstdlib>
#include <string>
#include <stdint.h>
using namespace std;
static char gFirstCity = 0;
static unsigned graph[50][50] = {0};
static unsigned minTour = 0xffffffff;
void swap (char *x, char *y)
{
char temp;
temp = *x;
*x = *y;
*y = temp;
}
void permute(char* cities, unsigned start, unsigned length)
{
if (start == (length-1))
{
cout << endl;
unsigned cost =0;
cost+= graph[(unsigned)gFirstCity][(unsigned)*cities];
for(unsigned i = 0; i < length-1; i++ )
{
cost+=graph[(unsigned)cities[i]][(unsigned)cities[i+1]];
for(int i = 0; i < length; i++){
cout << (int)cities[i];
}
}
cost+=graph[(unsigned)cities[length-1]][(unsigned)gFirstCity];
for(int i = 0; i < length; i++){
cout << (int)cities[i];
}
if(cost<minTour){
minTour = cost;
}
}
else
{
for (unsigned j = start; j < length; j++)
{
swap((cities + start), (cities + j));
permute(cities, start + 1, length);
swap((cities + start), (cities + j));
}
}
}
int main()
{
string cities;
string line;
char command = 0;
unsigned city = 0;
while (getline(cin, line))
{
sscanf(line.c_str(), "%c %d", &command, &city);
if (command != 'c')
break;
cities.push_back((unsigned char)city);
}
gFirstCity = cities[0];
unsigned to = 0;
unsigned from = 0;
uint32_t cost = 0;
sscanf(line.c_str(), "%c %d %d %d", &command, &to, &from, &cost);
graph[to-1][from-1]=cost;
graph[from-1][to-1]=cost;
while (getline(cin, line))
{
sscanf(line.c_str(), "%c %d %d %d", &command, &to, &from, &cost);
graph[to-1][from-1]=cost;
graph[from-1][to-1]=cost;
}
permute((char*)cities.c_str()+1, 0, cities.length()-1);
cout << minTour << endl;
return EXIT_SUCCESS;
在代码中添加了一些调试输出后,最大的问题似乎是您的算法不一致地混合了数组索引和城市。
例如,您的gStartCity
用作数组索引(从0开始),但实际上是一个城市编号(从1开始)。
你在实际获取成本时使用数组索引1-5,但你将成本分配给数组索引0-4。
我相信您可以通过将两组 graph[][]
作业更改为:
来获得预期的结果
graph[to][from]=cost;
graph[from][to]=cost;
graph[][]
的定义将允许在不覆盖其他内容的情况下进行此操作,并且您的寿命不足以使该算法计算出 49 个城市的最佳路径,因此差异无关紧要(49城市将需要大约 6E+62 条可能的路径;即使您每秒可以检查一百万条路径,这也只需要大约 20,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000 年的计算时间。
你的代码很难阅读和遵循,所以我不确定如何最好地解决你在大多数数组索引上偏离 1 的基本问题,但至少这应该得到它 运行 更接近您期望的方式。
我花了几个小时试图找出我的程序有什么问题,但我无法弄清楚。这是一个最低旅游成本的项目。 (TSP)
c 代表城市,a 代表弧形(2 个城市之间的旅行费用)
我用来测试的输入:
c 1
c 2
c 3
c 4
c 5
a 1 2 1400
a 1 3 1800
a 1 4 4000
a 1 5 3500
a 2 3 1200
a 2 4 3400
a 2 5 3600
a 3 4 2300
a 3 5 2700
a 4 5 2100
这是我的代码。上面的输入应该给出 10500 minTour,但它显示 5600。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cassert>
#include <sstream>
#include <cstdlib>
#include <string>
#include <stdint.h>
using namespace std;
static char gFirstCity = 0;
static unsigned graph[50][50] = {0};
static unsigned minTour = 0xffffffff;
void swap (char *x, char *y)
{
char temp;
temp = *x;
*x = *y;
*y = temp;
}
void permute(char* cities, unsigned start, unsigned length)
{
if (start == (length-1))
{
cout << endl;
unsigned cost =0;
cost+= graph[(unsigned)gFirstCity][(unsigned)*cities];
for(unsigned i = 0; i < length-1; i++ )
{
cost+=graph[(unsigned)cities[i]][(unsigned)cities[i+1]];
for(int i = 0; i < length; i++){
cout << (int)cities[i];
}
}
cost+=graph[(unsigned)cities[length-1]][(unsigned)gFirstCity];
for(int i = 0; i < length; i++){
cout << (int)cities[i];
}
if(cost<minTour){
minTour = cost;
}
}
else
{
for (unsigned j = start; j < length; j++)
{
swap((cities + start), (cities + j));
permute(cities, start + 1, length);
swap((cities + start), (cities + j));
}
}
}
int main()
{
string cities;
string line;
char command = 0;
unsigned city = 0;
while (getline(cin, line))
{
sscanf(line.c_str(), "%c %d", &command, &city);
if (command != 'c')
break;
cities.push_back((unsigned char)city);
}
gFirstCity = cities[0];
unsigned to = 0;
unsigned from = 0;
uint32_t cost = 0;
sscanf(line.c_str(), "%c %d %d %d", &command, &to, &from, &cost);
graph[to-1][from-1]=cost;
graph[from-1][to-1]=cost;
while (getline(cin, line))
{
sscanf(line.c_str(), "%c %d %d %d", &command, &to, &from, &cost);
graph[to-1][from-1]=cost;
graph[from-1][to-1]=cost;
}
permute((char*)cities.c_str()+1, 0, cities.length()-1);
cout << minTour << endl;
return EXIT_SUCCESS;
在代码中添加了一些调试输出后,最大的问题似乎是您的算法不一致地混合了数组索引和城市。
例如,您的gStartCity
用作数组索引(从0开始),但实际上是一个城市编号(从1开始)。
你在实际获取成本时使用数组索引1-5,但你将成本分配给数组索引0-4。
我相信您可以通过将两组 graph[][]
作业更改为:
graph[to][from]=cost;
graph[from][to]=cost;
graph[][]
的定义将允许在不覆盖其他内容的情况下进行此操作,并且您的寿命不足以使该算法计算出 49 个城市的最佳路径,因此差异无关紧要(49城市将需要大约 6E+62 条可能的路径;即使您每秒可以检查一百万条路径,这也只需要大约 20,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000 年的计算时间。
你的代码很难阅读和遵循,所以我不确定如何最好地解决你在大多数数组索引上偏离 1 的基本问题,但至少这应该得到它 运行 更接近您期望的方式。