洛谷P1433吃奶酪
Title
思路
先预处理dis
设f[i][j]为i点状态j的距离
f[i][2i-1]=dis[0][i]
f[j][i]=min(f[j][i],f[k][i-2j-1]+dis[k][j])
1<=j,k<=n
ans=min(f[i][2n-1])
代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
double x[20],y[20],dis[20][20],f[20][32769];
int main()
{
ios::sync_with_stdio(false);
int n,i,j,k;
double ans;
memset(f,0x7f7f7f7f,sizeof(f));
for(cin>>n,x[0]=y[0]=0,dis[0][0]=0,i=1; i<=n; i++)
for(cin>>x[i]>>y[i],j=0; j<i; j++)
dis[i][j]=dis[j][i]=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
for(i=1; i<=n; i++)f[i][1<<(i-1)]=dis[0][i];
for(i=1; i<(1<<n); i++)
for(j=1; j<=n; j++)
if(i&(1<<(j-1)))
for(k=1; k<=n; k++)
if(i&(1<<(k-1))&&j!=k)
f[j][i]=min(f[j][i],f[k][i-(1<<(j-1))]+dis[k][j]);
for(ans=0x7f7f7f7f,i=1; i<=n; i++)ans=min(ans,f[i][(1<<n)-1]);
printf("%.2lf",ans);
return 0;
}