Остап Бендер снова пытается получить причитающиеся драгоценности, но на этот раз они были заперты в шкатулке, для открытия которой необходимо иметь N ключей. По закономерной случайности каждый из ключей был спрятан в одном из N стульев, распроданных на недавнем аукционе. После аукциона эти стулья были развезены в N городов.
И вот теперь Остап решился на новую безумную затею: заехать в каждый из городов и, провернув в каждом из них аферу, выкрасть необходимые ключи. Чтобы избежать конфликтов с недоброжелателями, Остап не хочет больше одного раза появляться в каком-либо городе. Также у Остапа есть список цен за проезд между каждой парой городов. Изначально Остап находится в городе под номером 1 и после посещения всех городов может незаметно скрыться из этой страны.
Помогите Остапу найти порядок посещения городов, при котором ему потребуется потратить как можно меньше средств на странствия, и тогда, возможно, он поделится с Вами добытыми бриллиантами.
Формат входных данных
Первая строка содержит единственное число N — количество городов (1 ≤ N ≤ 17).
Следующие N строк содержат по N целых неотрицательных чисел. j-тое число в i-й строке означает стоимость проезда из города i в город j (0≤ a_{ij} ≤100). Если a_{ij} > 0, то проезд стоит a_{ij} рублей, иначе — это означает, что из города i в j невозможно проехать напрямую.
Формат результата
В первой строке выведите минимальную сумму денег, необходимую для посещения всех городов Остапом. В следующей строке выведите N чисел — порядок посещения городов, при котором эта сумма достигается. Если затею Остапа невозможно вывести, то в единственной строке выходного файла выведите число -1.
Есть код, скорее всего это динамика по подмаскам.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
#define ll long long
ll mod = 1000000007;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<vector<int>> gr(n, vector<int>(n));
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
cin >> gr[i][j];
}
}
vector<vector<int>> dp((1 << n), vector<int>(n,-1)),pref((1 << n), vector<int>(n, -1));
for (int i = 0; i < n; ++i) {
dp[1 << i][i] = 0;
pref[1 << i][i] = i;
}
for (int mask = 2; mask < (1 << n); ++mask) {
for (int p = 0; p < n; ++p) {
if ((mask >> p) & 1) {
for (int g = 0; g < n; ++g) {
if ((mask >> g) & 1 && g != p && gr[g][p] != 0) {
if ((dp[mask][p] == -1 || (dp[mask ^ (1 << p)][g] + gr[g][p] < dp[mask][p])) && dp[mask ^ (1 << p)][g]!=-1) {
dp[mask][p] = dp[mask^(1<<p)][g] + gr[p][g];
pref[mask][p] = g;
}
}
}
}
}
}
if (dp[(1 << n) - 1][0] != -1) {
cout << dp[(1 << n) - 1][0] << "\n";
int mask = (1 << n) - 1, p = 0;
while (mask != 0) {
int p1 = pref[mask][p];
cout << p + 1 << " ";
mask = mask ^ (1 << p);
p = p1;
}
}
else {
cout << -1;
}
}
Идея такая dp[mask][i] - минимальная сумма при вершинах из маски, при этом путь оканчивается в вершине i. Пересчёт идёт через подмаску, которая не содержит i вершину, и все возможные конечные вершины, которые есть в подмаске. Массив pref хранит вершину, через которую мы пересчитали значение, поэтому через него можно восстановить путь. По идее ответ находится в dp[ (1 << n) - 1 ][ 0 ], т.к. нам нет разницы конечная она или начально, просто изменится порядок обхода вершин на противоположный. Данный код должен работать за O(n^{2}). Однако этот код по какой-то причине не работает. Он выдаёт неправильный ответ. Уже не один час пытаюсь найти ошибку, но всё тщетно. Помогите, пожалуйста.