只访问选定城市并返回开始的最低成本

Minimum cost to visit only selected cities and come back to start?

本文关键字:开始 低成本 返回 访问 城市      更新时间:2023-10-16

我了解旅行推销员的问题。假设我只想访问选定的城市,然后回来开始,该怎么做?

假设我的成本矩阵是

  A B C D
A 0 1 2 1
B 1 0 1 2
C 2 1 0 1
D 1 2 1 0

如果我想参观所有的城市并回到A。我的最短路径是A->B->C->D,最小距离是4

假设我只想访问B和D。我如何找到最小距离?

这是修改旅行推销员的问题吗?有人能帮我做暴力算法吗?

您可以首先运行Floyd-Warshall来计算所有节点对之间的最短路径。请参阅维基百科文章。一旦你有了精简的成本矩阵,你就可以消除所有你不感兴趣的城市。从那里开始,就是标准的旅行推销员。

由于旅行推销员是NP完全的,所以在它之前运行Floyd Warshall对复杂性来说并不重要。

如果你想要完整的路线(包括绕过无趣的城市以缩短路径),你必须回到Floyd Warshall并重建路径。

我手头没有代码,但这里有一些建议和伪代码可以帮助您:我会通过在内存中存储一个向量和上面的距离矩阵来解决这个问题。类似于:

struct Location{
bool visited;
bool mustVisit;
}
Vector<Location> locationVec;

用问题中的位置填充向量,标记是否必须访问这些位置,并始终将visited设置为false。然后是有趣的部分!您需要创建位置Vec的排列。我会递归地这样做,类似于:

void addLocation(int & curLength, int & maxLength, int & curDistance, Vector<Location> &locationVec, Location* lastVisited)
if(curLenth == maxLength){
//check if currentDistance is less than the previously generated best difference, if so
//replace it
lastVisited->visited=0;
return;
}
//Add the next location
for (int& i : locationVec){
//Check if the location has been visited, and if it must be visited.
//If so: mark as visited, point lastVisited to it, and break
//Also add from lastVisited to the new location to your curDistance
curLength++;
}
addLocation(curLength, maxLength, curDistance, locationVec, lastVisited);
return;
}

这应该会让你开始。当您将visited从visited=1更改为visited=0时,请记住减去currentDist,因为您基本上是在"取消访问"城市。您可能还需要跟踪lastlastvisited,具体取决于您的具体实现。

如果你需要加快速度(你可能会的,旅行推销员很慢),请查看Branch and Bound:http://en.wikipedia.org/wiki/Branch_and_bound