洛谷P1433吃奶酪
吃奶酪
题目描述
房间里放着
输入格式
第一行有一个整数,表示奶酪的数量
第
输出格式
输出一行一个实数,表示要跑的最少距离,保留
样例 #1
样例输入 #1
4
1 1
1 -1
-1 1
-1 -1
样例输出 #1
7.41
提示
数据规模与约定
对于全部的测试点,保证
提示
对于两个点
这是一道比较明显的状压dp
状态表示 f[i][j]:在第j个点,当前状态为i的所有路径,属性:最小值
状态计算:可以从前往后推,也可以从后往前考虑,从前往后考虑的话,枚举j这个点可能由哪些点转移过来f[i |(1<<(k - 1))][k] = min(f[i |(1<<(k - 1))][k], f[i][j] + a[j][k]);
#include <iostream>
#include <algorithm>
#include <cstring>
#include <math.h>
using namespace std;
const int N = 20, M = 1 << N;
double f[M][N], a[N][N];
struct point
{
double x, y;
}p[N];
int main()
{
// freopen("1.in","r",stdin);
int n;cin >> n;
for(int i = 0; i < (1 << n); ++ i)
for(int j = 0; j <= n; ++j)
f[i][j] = 2e9;
for(int i = 1; i <= n; ++i)
{
//x,y均为实数
double x, y; cin >> x >> y;
p[i] = {x, y};
}
//预处理出来每个点到每个点的距离
for(int i = 0; i <= n; ++i)
for(int j = 0; j <= n; ++ j)
a[i][j] = sqrt((p[i].x - p[j].x) * (p[i].x - p[j].x) + (p[i].y - p[j].y) * (p[i].y - p[j].y));
//因为第0个转移时不符合状态转移方程,这时我们单独跑一遍0到每个点的状态
for(int i=1;i<=n;++i) f[1<<(i-1)][i]=a[0][I];
//此时我们只用考虑正常的转移
for(int i=0;i<(1<<n);++i)
{
for(int j=1;j<=n;++j)
//只有当第j位为1时状态i才表示已经在第j个点了
if(i&(1<<(j-1)))
{
for(int k=1;k<=n;++k)
//只有当状态i的第k位为0也就是说还没有到达过,我们才用k去转移
if(!(i&(1<<(k-1)))) f[i|(1<<(k-1))][k]=min(f[i|(1<<(k-1))][k],f[i][j]+a[j][k]);
}
}
double res = 2e9;
//找到符合状态的所有值中的最小值
for(int i = 1; i <= n; ++ i) res = min(res, f[(1<<n)-1][i]);
printf("%.2lf",res);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署