火龙信奥
  • 首页
  • 课程
  • 题库
  • 打卡
    • 代码对战
    • 快速对战
  • 题单
  • 团队
  • 荣誉墙
  • 商城
  • 登录 / 注册

luogu1433

作者: 作者的头像   huolong , 时间:2024-08-24 11:26:12 , 所有人可见, 阅读  11

#include <bits/stdc++.h>
using namespace std;

int n;                      // 奶酪的数量
double a[16][3];            // 用于存储每块奶酪的坐标(x, y)
double dp[1<<16][16], ans;  // dp[s][i] 表示状态 s 下,以第 i 个奶酪结尾的最小路径长度,ans 用于存储最终答案

// 计算第 x 个奶酪和第 y 个奶酪之间的欧氏距离
double dis(int x, int y) {
    return sqrt((a[x][1]-a[y][1])*(a[x][1]-a[y][1])+(a[x][2]-a[y][2])*(a[x][2]-a[y][2]));
}

int main() {
    cin >> n;  // 读取奶酪的数量
    for (int i = 1; i <= n; i++) cin >> a[i][1] >> a[i][2];  // 读取每块奶酪的坐标

    n++;  // 增加一个虚拟的终点,代表返回原点
    memset(dp, 0x7f, sizeof(dp));  // 初始化 dp 数组为一个很大的值,相当于无穷大
    dp[1][0] = 0;  // 初始状态:从原点出发,未经过任何奶酪,距离为 0

    // 枚举所有可能的状态 s,s 是一个整数,二进制表示哪些奶酪被吃过
    for (int s = 0; s <= (1<<n)-1; s++) {
        // 枚举当前状态 s 下的所有可能的结尾点 i
        for(int i = 1; i <= n-1; i++) {
            if ((s & (1 << i)) == 0) continue;  // 如果 i 没有在状态 s 中被访问过,跳过
            int x = s - (1 << i);  // 去掉 i 后的状态 x
            // 寻找能转移到当前状态的前一个状态 j
            for(int j = 0; j <= n-1; j++) {
                if ((x & (1 << j)) == 0) continue;  // 如果 j 没有在状态 x 中被访问过,跳过
                dp[s][i] = min(dp[s][i], dp[x][j] + dis(j, i));  // 更新 dp[s][i],取最小值
            }
        }
    }

    int x = (1 << n) - 1;  // 最终状态,所有奶酪都被访问过
    ans = dp[x][1];  // 初始化 ans 为 dp[x][1],即以第一个奶酪结尾的最短路径
    for (int i = 2; i < n; i++) ans = min(dp[x][i], ans);  // 遍历所有可能的结尾点,取最小值

    printf("%.2lf", ans);  // 输出最短路径长度,保留两位小数
    return 0;
}


—— 本文来自火龙信奥(义乌睿码科技):义乌青少年信息学奥赛与编程教育平台,专注 CSP-J/S、NOIP、GESP 竞赛培训,线上线下融合教学,助力编程升学。网址:hlcoding.com

©2026加盟我们 | 关于我们 | ACM课程 | 常见问题 | 成果墙 | 评测记录 | 浙ICP备2021013995号
在线画图 | OI WIki | 打字练习
火龙信奥
请输入登录信息


请完成安全验证
验证码底图 滑块
向右拖动滑块完成验证
请输入用户名 / 绑定的手机号码



请输入注册信息(手机号验证码注册)





验证码5分钟有效,60秒内不可重复获取,每日最多3次

微信登录

微信登录二维码

正在生成二维码...

账号已过期,请续期。
去续期

绑定手机号

📱

为了更好地保护您的账号安全,享受完整的平台服务

请您尽快绑定手机号码