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;
	
}
posted @ 2024-09-13 14:58  lipu123  阅读(18)  评论(0)    收藏  举报