P1433 吃奶酪
https://www.luogu.com.cn/problem/P1433
吃奶酪
题目描述
房间里放着 \(n\) 块奶酪。一只小老鼠要把它们都吃掉,问至少要跑多少距离?老鼠一开始在 \((0,0)\) 点处。
输入格式
第一行有一个整数,表示奶酪的数量 \(n\)。
第 \(2\) 到第 \((n + 1)\) 行,每行两个实数,第 \((i + 1)\) 行的实数分别表示第 \(i\) 块奶酪的横纵坐标 \(x_i, y_i\)。
输出格式
输出一行一个实数,表示要跑的最少距离,保留 \(2\) 位小数。
样例 #1
样例输入 #1
4
1 1
1 -1
-1 1
-1 -1
样例输出 #1
7.41
提示
数据规模与约定
对于全部的测试点,保证 \(1\leq n\leq 15\),\(|x_i|, |y_i| \leq 200\),小数点后最多有 \(3\) 位数字。
提示
对于两个点 \((x_1,y_1)\),\((x_2, y_2)\),两点之间的距离公式为 \(\sqrt{(x_1-x_2)^2+(y_1-y_2)^2}\)。
\(2022.7.13\):新增加一组 \(\text{Hack}\) 数据。
对于这个题,这个就是类似于之前写的旅行商问题,https://www.cnblogs.com/lipu123/p/18402619
我们定义一个状态 f[i][j] ,其中 i 是一个二进制数,每一位表示这个点是否被经过, j 表示当前走到哪一个点。
#include<iostream>
#include<algorithm>
#include<vector>
#include<math.h>
#include<cstring>
using namespace std;
const int maxn=20;
double x[maxn],y[maxn];
double f[1<<maxn][maxn];//状态是S,到j
int n;
const double inf=1000000005;
double dist(int j,int k){
double w=sqrt((x[j]-x[k])*(x[j]-x[k])+(y[j]-y[k])*(y[j]-y[k]));
return w;
}
int main(){
cin>>n;
for(int i=0;i<(1<<16);i++) {
for(int j=0;j<=20;j++) f[i][j]=inf;
}
for(int i=1;i<=n;i++){
scanf("%lf %lf",&x[i],&y[i]);
}
x[0]=0.0,y[0]=0.0;
f[1][0]=0.0;
n++;
for(int s=1;s<(1<<n);s++){
for(int i=0;i<n;i++){
if(!((s>>i)&1)){
for(int j=0;j<n;j++){
if(((s>>j)&1)){
f[s|(1<<i)][i]=min(f[s|(1<<i)][i],f[s][j]+dist(i,j));
}
}
}
}
}
double ans=inf;
for(int i=1;i<n;i++){
ans=min(ans,f[(1<<n)-1][i]);
}
printf("%.2lf",ans);
return 0;
}