#include <bits/stdc++.h>
using namespace std;
int n; // 奶酪的数量
double a[16][3]; // 用于存储每块奶酪的坐标(x, y)
double dp[1<<16][16], ans; // dp[s][i] 表示状态 s 下,以第 i 个奶酪结尾的最小路径长度,ans 用于存储最终答案
// 计算第 x 个奶酪和第 y 个奶酪之间的欧氏距离
double dis(int x, int y) {
return sqrt((a[x][1]-a[y][1])*(a[x][1]-a[y][1])+(a[x][2]-a[y][2])*(a[x][2]-a[y][2]));
}
int main() {
cin >> n; // 读取奶酪的数量
for (int i = 1; i <= n; i++) cin >> a[i][1] >> a[i][2]; // 读取每块奶酪的坐标
n++; // 增加一个虚拟的终点,代表返回原点
memset(dp, 0x7f, sizeof(dp)); // 初始化 dp 数组为一个很大的值,相当于无穷大
dp[1][0] = 0; // 初始状态:从原点出发,未经过任何奶酪,距离为 0
// 枚举所有可能的状态 s,s 是一个整数,二进制表示哪些奶酪被吃过
for (int s = 0; s <= (1<<n)-1; s++) {
// 枚举当前状态 s 下的所有可能的结尾点 i
for(int i = 1; i <= n-1; i++) {
if ((s & (1 << i)) == 0) continue; // 如果 i 没有在状态 s 中被访问过,跳过
int x = s - (1 << i); // 去掉 i 后的状态 x
// 寻找能转移到当前状态的前一个状态 j
for(int j = 0; j <= n-1; j++) {
if ((x & (1 << j)) == 0) continue; // 如果 j 没有在状态 x 中被访问过,跳过
dp[s][i] = min(dp[s][i], dp[x][j] + dis(j, i)); // 更新 dp[s][i],取最小值
}
}
}
int x = (1 << n) - 1; // 最终状态,所有奶酪都被访问过
ans = dp[x][1]; // 初始化 ans 为 dp[x][1],即以第一个奶酪结尾的最短路径
for (int i = 2; i < n; i++) ans = min(dp[x][i], ans); // 遍历所有可能的结尾点,取最小值
printf("%.2lf", ans); // 输出最短路径长度,保留两位小数
return 0;
}
—— 本文来自火龙信奥(义乌睿码科技):义乌青少年信息学奥赛与编程教育平台,专注 CSP-J/S、NOIP、GESP 竞赛培训,线上线下融合教学,助力编程升学。网址:hlcoding.com