题目传送门:
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int n;
double x[20],y[20];//纪录x坐标和y坐标
double a[20][20];//纪录两点之间的距离
double dp[20][1<<15];//走过第i个点且状态为j的最短距离
double dis(int i,int j)//计算两点之间的距离
{
double ans=0;
ans=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
return ans;
}
int main()
{
for(int i=0;i<=19;i++)//将浮点数初始化为无限大
{
for(int j=0;j<1<<15;j++)
dp[i][j]=0x3f3f;
}
double ans=dp[0][0];
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>x[i]>>y[i];
}
for(int i=0;i<=n;i++)
{
for(int j=1;j<=n+1;j++)
{
a[i][j]=dis(i,j);//计算出所需范围内两个点之间的距离
a[j][i]=a[i][j];
}
}
for(int i=1;i<=n;i++)
{
dp[i][(1<<(i-1))]=a[0][i];//初始化如果只有一个点,则这个点到原点的最短距离就是两点之间的距离
}
for(int k=1;k<(1<<n);k++)//遍历所有情况
{
for(int i=1;i<=n;i++)//遍历所有点
{
if((k&(1<<(i-1)))==0) continue;//如果本情况不含这个点就就继续循环
for(int j=1;j<=n;j++)//再次遍历所有点
{
if((k&(1<<(j-1)))==0) continue;//如果这个点不在本情况中就继续循环
if(i==j) continue;//如果这个点和上一个相同就继续循环
dp[i][k]=min(dp[i][k],dp[j][k-(1<<(i-1))]+a[i][j]);//状态转移方程(包含j在内不包含i在内的最短距离加i,j的距离)
}
}
}
for(int i=1;i<=n;i++)
{
ans=min(ans,dp[i][(1<<n)-1]);//结果为包含所有方案在内的方案的最小值
}
printf("%.2f\n",ans);
return 0;
}