我正在尝试创建一个本地搜索启发式来解决TSP,这个过程似乎失败了。我已经生成了一个随机哈密顿循环并将其存储在outgoing []中,其中outgoing [i]表示起始于i的一个边指向的顶点。距离[a] [b]表示从顶点a到顶点b的距离。然而,每当我运行该代码时,该算法不是优化我在传出中传递的哈密顿循环,而是简单地创建新的循环0->数量-2-> 1->数量-1。它应该简单地重复切换输出顶点,如果它可以改善顶点到其输出顶点的距离。我可能忽略了一些小事,但我根本无法弄清楚我做错了什么。顺便说一句,我将运行这么多次,这就是布尔改变的用途。
for(int i = 0; i < numcities; i++)
{
for(int j = i+1; j < numcities; j++)
{
if(distances[i][outgoing[i]] + distances[j][outgoing[j]] > distances[i][outgoing[j]] + distances[j][outgoing[i]] && i != outgoing[j] && j != outgoing[i])
{
changed = true;
int temp = outgoing[j];
outgoing[j] = outgoing[i];
outgoing[i] = temp;
}
}
}
答案 0 :(得分:1)
问题在于,当你交换outgoing[i]
和outgoing[j]
时,你会创建两个小子 - 两个较小的周期。
例如,假设numcities=6
并且您的首发之旅为0 1 2 3 4 5.假设您的if
声明适用于i=1
,j=3
。您的代码集outgoing[1] = 4
和outgoing[3] = 2
。所以代码认为自outgoing[1] = 4
以来巡回演出现在是0 1 4 5。这不是你正在进行的巡回演出,但我认为这是基本的想法。
要解决此问题,您需要将游览分为3个部分 - (A)部分直至并包括城市i
,(B)i
和{{1之间的部分(包括j
)和(C)j
之后的部分。当您交换边缘时,您需要重新配置巡视,因此(A)与之前相同,然后部分(B)反转,然后部分(C)完好无损。
所以在我的例子中,部分(A)是0 1,部分(B)是2 3,部分(C)是4 5.打破边缘1-2和3-4,然后重新连接,你得到游览0 1 3 2 4 5.
您在此处实施的内容称为 2-opt 。您可以在很多地方找到更多相关信息。