悬关,是一个状压思路的剪枝
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
int n;
bool flag[15];
double ans = 1e18, x[15], y[15], vis[70000][15];
inline double cal(double x, double y, double a, double b)
{
return sqrt((x - a) * (x - a) + (y - b) * (y - b));
}
void dfs(int step, int last, int status, double sum)
{
if (sum >= ans)
{
return;
}
if (step > n)
{
ans = min(ans, sum);
return;
}
for (register int i = 1; i <= n; i++)
{
if (flag[i])
{
continue;
}
int st = status + (1 << (i - 1));
double temp = cal(x[i], y[i], x[last], y[last]);
if (vis[st][i] != 0 && vis[st][i] <= sum + temp)
{
continue;
}
flag[i] = true;
vis[st][i] = sum + temp;
dfs(step + 1, i, st, vis[st][i]);
flag[i] = false;
}
}
//15 0 0 1 1 1 -1 -1 1 -1 -1 2 2 2 0 2 -2 0 -2 -2 -2 -2 0 -2 2 0 2 1 3 1 4
int main()
{
cin >> n;
for (register int i = 1; i <= n; i++)
{
cin >> x[i] >> y[i];
}
for (register int i = 1; i < n; ++i)
for (register int j = i + 1; j <= n; ++j)
if (x[i] == x[j] && y[i] == y[j]) {
for (register int k = j; k < n; ++k)
{
x[j] = x[k];
y[j] = y[k];
}
--j;
--n;
}
dfs(1, 0, 0, 0);
cout << fixed << setprecision(2) << ans;
return 0;
}