По этой формуле рекурсии для динамического программирования (Алгоритм Хелда-Карпа) можно найти минимальную стоимость. Я ввел этот код на 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
)
Я знаю о динамическом программировании, которое предотвращает дублирование вычислений (например, функция Фибоначчи), но оно не имеет дублирующих вычислений, потому что, если мы нарисуем дерево этой функции, мы увидим, что аргументы функции (т.е. S
и i
в формуле и как на картинке ниже ) никогда не бывают одинаковыми, и нет дублирующих вычислений.
Мой вопрос: на этот раз O (n!)?
картинка : Если да, то почему? Эта функция точно такая же, как и формула, и она делает то же самое. В чем проблема? Делает ли он дублирующие вычисления?
Временная сложность вашего алгоритма составляет O (n!). Легко понять, что ваш код угадывает следующий узел пути. А их ровно n! разные пути. Ваш код фактически подсчитывает одно и то же значение несколько раз. Например, если вы запускаете TSP({1, 2, 3, 4}, 0)
, и он пытается упорядочить {1, 2, 3}
и {2, 1, 3}
. Понятно, что код запустится TSP({4}, 3)
два раза. Чтобы избавиться от этого, сохраните уже рассчитанные ответы для масок и запустите node.
Это единственная проблема, которую я вижу. Если размер S равен 3, он переходит к оператору if (neighbor.size() == 0)
несколько раз.
Я не понимаю что ты сказал. Но мой вопрос: если размер S
равен 3, за исключением листьев, у нас нет повторяющихся вычислений, верно?
У нас нет повторяющихся расчетов
Спасибо, я понял. Единственная проблема в том, что он вычисляет дубликаты, верно? Нет ли других проблем? И что этот код не считается дубликатом, когда число членов S равно 3?