根据此用于动态规划的递归公式(Held–Karp算法),可以找到最低成本。我在C ++中输入了此代码,并且实现了这一点(neighbor
向量是相同的集合,并且v
是成本矩阵):
递归公式:
C(i,S) = min { d(i,j) + C(j,S-{j}) }
我的代码:
#include <iostream>
#include <vector>
#define INF 99999
using namespace std;
vector<vector<int>> v{ { 0, 4, 1, 3 },{ 4, 0, 2, 1 },{ 1, 2, 0, 5 },{ 3, 1, 5, 0 } };
vector<int> erase(vector<int> v, int j)
{
v.erase(v.begin() + j);
vector<int> vv = v;
return vv;
}
int TSP(vector<int> neighbor, int index)
{
if (neighbor.size() == 0)
return v[index][0];
int min = INF;
for (int j = 0; j < neighbor.size(); j++)
{
int cost = v[index][neighbor[j]] + TSP(erase(neighbor, j), neighbor[j]);
if (cost < min)
min = cost;
}
return min;
}
int main()
{
vector<int> neighbor{ 1, 2, 3 };
cout << TSP(neighbor, 0) << endl;
return 0;
}
实际上,该erase
函数j
从集合中删除了元素(即neighbor
向量)
我知道动态编程可以防止重复计算(例如Fibonacci函数),但是它没有重复计算,因为如果我们绘制此函数的树,我们会看到函数的参数(即S
andi
在公式中,如下图所示)是永远不一样,也没有重复的计算。我的问题是,这次是O(n!)吗?
你的算法时间复杂度为O(n!)。很容易理解你的代码正在猜测路径的下一个节点。恰好有n个!不同的路径。你的代码实际上多次计数相同的值。例如,如果你运行TSP({1, 2, 3, 4}, 0)
并尝试命令order{1, 2, 3}
和{2, 1, 3}
。很明显,代码将运行TSP({4}, 3)
两次。为了摆脱这个存储,已经为掩码和起始节点计算出了答案。
谢谢,我明白了。唯一的问题是它计算重复项,对吗?还有其他问题吗?并且当S成员的数量为3时,此代码不算作重复项吗?
那是我唯一看到的问题。如果S的大小为3,它将
if (neighbor.size() == 0)
多次执行语句。我不明白你在说什么。但是我的问题是
S
,除叶子以外,的大小是否为3,我们没有重复计算,对吗?我们没有重复的计算