// ZZQF5677
#include <bits/stdc++.h>
using namespace std;
int n, D;
double ans;
const int INF = 0x7f7f7f;
double dist(double x11, double y11, double x22, double y22) {
double op = sqrt(abs(x11 - x22) * abs(x11 - x22) + abs(y11 - y22) * abs(y11 - y22));
if (op > D) {
return INF;
}
return op;
}
double d[25][25]; // 两点间的最短路。
int x[25], y[25];
double dp[1048577][25]; // 走到第几个点。
// 第几次(压缩)走到 j 点,走了的情况是 k,数组值是最小值,经过了相同的点,反正都走到了这个点,那肯定要最小的走法,不影响这个点下次向谁递归。。。
bool now = 0;
bool last = 1;
int h[25]; // 预处理每个点到哪一个点距离最近。
int main() {
//freopen("1.in", "r", stdin);
cin >> n >> D;
const int nn = n;
for (int i = 1; i <= n; i++) {
cin >> x[i] >> y[i];
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
d[i][j] = dist(x[i], y[i], x[j], y[j]);
if (d[i][j] > D) { // 一定要注意是单次飞行不超过 D!!!
d[i][j] = INF;
}
}
}
for (int k = 1; k <= n; k++) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
}
}
}
/*
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
}
}
*/
///
/*
一个点的状态从另一点 0 比自己少(或者等于)的状态进行转移,另一点的数值肯定比自己小(或者等于)
*/
memset(dp, INF, sizeof(dp));
dp[0][0] = 0;
dp[1][1] = 0;
for (int k = 0; k <= (1 << n) - 1; k++) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
// 我们记 k 为原状态(j)的,现在要转移到 i。
// i 号点 0 -> 1。
if ((k & (1 << (j - 1))) && !(k & (1 << (i - 1)))) {
dp[k | (1 << (i - 1))][i] = min(dp[k | (1 << (i - 1))][i], dp[k][j] + dist(x[i], y[i], x[j], y[j]));
}
// j 走到 i 号点,i 状态还是 1。
if ((k & (1 << (j - 1))) && (k & (1 << (i - 1)))) {
dp[k][i] = min(dp[k][i], dp[k][j] + dist(x[i], y[i], x[j], y[j]));
}
// dp[k | (1 << (i - 1))][i] = min(dp[k | (1 << (i - 1))][i], dp[k | (1 << (j - 1))][]);
}
}
}
/*
cout << dp[3][2] << "\n";
cout << dp[7][3] << "\n";
cout << dp[15][4] << "\n";
*/
ans = INF;
const int END = (1 << n) - 1;
for (int i = 1; i <= n; i++) {
ans = min(ans, dp[END][i] + d[i][1]);
}
cout << fixed << setprecision(2) << (ans + 0.00) << "\n";
return 0;
}
谢谢!!!