洛谷 P1523 旅行商简化版【线性dp+npc问题简化版】

news2025/4/7 17:19:51

原题链接:https://www.luogu.com.cn/problem/P1523

题目背景

欧几里德旅行商(Euclidean Traveling Salesman)问题也就是货郎担问题一直是困扰全世界数学家、计算机学家的著名问题。现有的算法都没有办法在确定型机器上在多项式时间内求出最优解,但是有办法在多项式时间内求出一个较优解。

为了简化问题,而且保证能在多项式时间内求出最优解,J.L.Bentley 提出了一种叫做 bitonic tour 的哈密尔顿环游。它的要求是任意两点 (a,b) 之间的相互到达的代价 dist(a,b)=dist(b,a) 且任意两点之间可以相互到达,并且环游的路线只能是从最西端单向到最东端,再单项返回最西端,并且是一个哈密尔顿回路。

题目描述

本题为著名的 NPC 难题的简化版本。

现在笛卡尔平面上有 (n≤1000) 个点,每个点的坐标为(x,y),-2^{31}<x,y<2^{31},且为整数),任意两点之间相互到达的代价为这两点的欧几里德距离,现要你编程求出最短 bitonic tour。

输入格式

第一行一个整数 n。

接下来 n 行,每行两个整数 x,y,表示某个点的坐标。

输入中保证没有重复的两点,保证最西端和最东端都只有一个点。

输出格式

一行,即最短回路的长度,保留 2位小数。

输入输出样例

输入 #1

7
0 6
1 0
2 3
5 4
6 1
7 5
8 2

输出 #1

25.58

说明/提示

题目来源

《算法导论(第二版)》 15-1

解题思路:

这个题目是npc问题的简化版,也就是旅行商问题的简化版,

简化之后很像:P1006 [NOIP2008 提高组] 传纸条

这俩个题目的解题思想非常的像,但是又不完全相同,因为传纸条这个题目走的过程中间俩个人是允许走同一个点的,只是效益只计算一次,但是这个题目俩个人不允许走同一个点,首先我们利用类似传纸条这题的思想对题目进行类似转换,对于本题我们同样可以将来回走,变为俩个人一起从西边的点走到东边的点,这样就将原问题转换为了有俩个人从最西边的点都走到最东边的点,并且中间的每个点走且只走一次,这样我们就可以根据传纸条这题的思想来设计状态了,注意走的过程中由于不能走同样的点,所以走的过程中必然一个在前一个在后,我们还需要对于所有点按照横坐标从小到达排序。

状态定义

定义f[i][j]表示后面那个人走到i这个点,前面那个人走到j这个点,并且i<j,并且1~j之间的所有点都走过一次了的最短距离。

初始化

由于必须从西往东依次走过每一个点,我们最开始一定后面那个人在1号点,前面那个人在2号点,所以初始化为f[1][2]=d[1][2]

状态转移

当前i在后面,j在前面,1~j之间的所有点都已经走过了,接下来要走的点是j+1,那么存在俩种情况

(1)让j走到j+1,i暂时不动

(2)让i走到j+1,j暂时不动,会导致i走到j前面,为了保证前后性,我们交换i,j的位置

j走到j+1,i暂时不动

  • f[i][j + 1] = min(f[i][j + 1], f[i][j] + d[j][j + 1]);

i走到j+1,j暂时不动,并且需要交换i,j位置,原本i变为j+1,j还是j,现在交换变为i变为j,j变为j+1,交换位置才能保证前面那个仍然在前面,后面那个也仍然在后面。

  • f[j][j + 1] = min(f[j][j + 1], f[i][j] + d[i][j + 1]);

最终答案

最后一步一定是前面那个人已经到达了n号点,后面那个人可以在中间的任意一个点,后面那个人还没有到达终点,然后后面那个人走到n号点(终点),所以答案就是所有的min(f[i][n]+d[i][n])(1<=i<n)

时间复杂度:第一维枚举后面那个人当前所在点,时间为O(n),第二维枚举前面那个人当前所在点,时间为O(n),最终时间复杂度为O(n^2),n=1000,最终时间就是1e6,这个时间复杂度是肯定可以过的。

空间复杂度:俩个数组都是二维,空间复杂度为O(n^2)。

cpp代码如下:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;

const int N = 1010;

int n;
struct points
{
    double x, y;
} a[N]; // 存储所有点的坐标
double f[N][N], d[N][N];

double get_distance(points u, points v) // 计算俩点之间的距离
{
    double dx = u.x - v.x, dy = u.y - v.y;
    return sqrt(dx * dx + dy * dy);
}
int main()
{
    cin >> n;
    for (int i = 1; i <= n; i++)
        scanf("%lf%lf", &a[i].x, &a[i].y);
    // 按照横坐标从小到达排序
    sort(a + 1, a + 1 + n, [&](points A, points B)
         { return A.x < B.x; });

    // 初始化距离数组d和dp数组f
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
        {
            d[i][j] = d[j][i] = get_distance(a[i], a[j]);
            f[i][j] = 1e30;
        }
    // 初始时走在后面的那个人在1号点,走在前面的那个人在2号点,由于必须是从习往东一次走每个点,所以最开始俩人必然在1,2号点
    f[1][2] = d[1][2];
    for (int i = 1; i < n; i++)
        for (int j = i + 1; j <= n; j++) // 前面那个人要在后面那个人前面,所以这里从i+1开始枚举
        {
            /*
                当前i在后面,j在前面,1~j之间的所有点都已经走过了,接下来要走的点是j+1,那么存在俩种情况
                (1)让j走到j+1,i暂时不动
                (2)让i走到j+1,j暂时不动
            */
            // j走到j+1,i暂时不动
            f[i][j + 1] = min(f[i][j + 1], f[i][j] + d[j][j + 1]);
            // i走到j+1,j暂时不动
            f[j][j + 1] = min(f[j][j + 1], f[i][j] + d[i][j + 1]);
        }
    /*
        最后一步一定是前面那个人已经到达了n号点,后面那个人可以在中间的任意一个点,后面那个人还没有到达终点,
        然后后面那个人走到n号点(终点),所以答案就是所有的min(f[i][n]+d[i][n]) (1<=i<n)
    */
    double ans = 1e30;
    for (int i = 1; i < n; i++)
        ans = min(ans, f[i][n] + d[i][n]);
    printf("%.2lf\n", ans);
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1388769.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2024 年企业要增强反脆弱性,IT 能够做什么?

新冠疫情被称为黑天鹅事件&#xff0c;而“黑天鹅”这个词的创造者纳西姆尼古拉斯塔勒布在另一本书《反脆弱&#xff1a;从不确定性中获益》&#xff08; CSDN博主读书笔记《反脆弱&#xff1a;从不确定性中获益》 &#xff09;中&#xff0c;则给出了面对随时可能出现的黑天鹅…

玖章算术NineData通过阿里云PolarDB产品生态集成认证

近日&#xff0c;玖章算术旗下NineData 云原生智能数据管理平台 (V1.0&#xff09;正式通过了阿里云PolarDB PostgreSQL版 (V11)产品集成认证测试&#xff0c;并获得阿里云颁发的产品生态集成认证。 测试结果表明&#xff0c;玖章算术旗下NineData数据管理平台 (V1.0&#xff…

Python源码23:海龟画图turtle画小狗狗

---------------turtle源码集合--------------- Python教程43&#xff1a;海龟画图turtle画小樱魔法阵 Python教程42&#xff1a;海龟画图turtle画海绵宝宝 Python教程41&#xff1a;海龟画图turtle画蜡笔小新 Python教程40&#xff1a;使用turtle画一只杰瑞 Python教程39…

❤ Uniapp使用一(文档和 API 篇)

❤ Uniapp使用一&#xff08;文档和 API 篇&#xff09; 一、介绍 uni-app官网&#xff1a;https://uniapp.dcloud.io/api/media/image?idpreviewimage 微信小程序官网&#xff1a;https://developers.weixin.qq.com/miniprogram/dev/api/media/image/wx.previewImage.html …

使用WAF防御网络上的隐蔽威胁之SQL注入攻击

SQL注入攻击是一种普遍存在且危害巨大的网络安全威胁&#xff0c;它允许攻击者通过执行恶意的SQL语句来操纵或破坏数据库。 这种攻击不仅能够读取敏感数据&#xff0c;还可能用于添加、修改或删除数据库中的记录。因此&#xff0c;了解SQL注入攻击的机制及其防御策略对于保护网…

Spring基于AOP(面向切面编程)开发

概述 AOP为Aspect Oriented Programming的缩写&#xff0c;意为&#xff1a;面向切面编程&#xff0c;通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续&#xff0c;是软件开发中的一个热点&#xff0c;也是Spring框架中的一个重要内容&…

使用WAF防御之网络上的隐蔽威胁(XSS攻击)

跨站脚本攻击&#xff08;XSS&#xff09;是一种常见且危险的威胁。它允许攻击者在用户浏览器上执行恶意脚本&#xff0c;窃取信息、篡改网页内容&#xff0c;甚至劫持用户会话。 什么是XSS攻击 定义&#xff1a;XSS攻击是一种代码注入技术&#xff0c;攻击者通过在目标网站上…

练习题 删除链表的倒数第N个结点

题目 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5]示例 2&#xff1a; 输入&#xff1a;head [1], n 1 输出&#xff1a;[]示例 3&#…

潍坊数字孪生元宇宙赋能智能制造,助力工业制造业数字化转型

潍坊工业元宇宙数字孪生赋能智能制造&#xff0c;助力工业制造业数字化转型。在当今数字化时代&#xff0c;工业智能制造已成为制造业发展的必然趋势。潍坊市作为山东省的重要工业基地&#xff0c;积极探索数字孪生技术在工业智能制造领域的应用&#xff0c;为制造业企业数字化…

ant-design-vue Notification 通知提醒框 内容换行

直接上代码 const msg errArr.map((message, index) > ${index 1}. ${message};) notification.open({message: ${statu.moduleName} 告警信息,description: () > {// 将msg所有;替换为\n换行符const res msg.replaceAll(;, \n)return h(pre,{style: {overflow: scro…

Transformer简单理解

目录 一、CNN存在的问题&#xff1a;二.Transformer整理架构分析&#xff1a;1.Linear Projection of Flattened Patches层形成Patch&#xff1a;2.对每个Patch进行位置编码Position Embedding&#xff1a;3.Transformer Encoder: 三.公式解读&#xff1a; 一、CNN存在的问题&a…

为什么使用 atan2(sin(z), cos(z)) 进行角度归一化?

文章目录 为什么使用 atan2(sin(z), cos(z)) 进行归一化&#xff1f;为什么归一化后的角度等于原始角度&#xff1f; atan2 方法返回 -π 到 π 之间的值&#xff0c;代表点 (x, y) 相对于正X轴的偏移角度。这个角度是逆时针测量的&#xff0c;以弧度为单位。关于 atan2 函数为…

【JAVA WEB】 Filter过滤器详解

目录 1&#xff0c;Filter 1.1 Filter概述 1.2 Filter快速入门 1.2.1 开发步骤 1.2.2 代码演示 1.3 Filter执行流程 1.4 Filter拦截路径配置 1.5 过滤器链 1.5.1 概述 1.5.2 代码演示 1.5.3 问题 1.6 案例 1.6.1 需求 1.6.2 分析 1.6.3 代码实现 1.6.3.1 创建Fi…

ERP系统怎么选 企业ERP管理系统选型建议

市面上有众多的ERP系统&#xff0c;而由于不同软件供应商的发展策略不同&#xff0c;导致不同ERP系统的侧重点也不同。例如有针对企业某一类管理需求的ERP系统&#xff0c;例如财务管理软件&#xff0c;进销存管理软件&#xff0c;仓库管理软件等。还有针对企业资源整合&#x…

element-ui表单验证同时用change与blur一起验证

项目场景&#xff1a; 提示&#xff1a;这里简述项目相关背景&#xff1a; 当审批时不通过审批意见要必须输入&#xff0c; 1&#xff1a;如果用change验证的话删除所有内容时报错是massage的提示&#xff0c;但是在失去焦点的时候报错就成了英文&#xff0c;如下图&#xf…

【iOS】数据存储方式总结(持久化)沙盒结构

在iOS开发中&#xff0c;我们经常性地需要存储一些状态和数据&#xff0c;比如用户对于App的相关设置、需要在本地缓存的数据等等&#xff0c;本篇文章将介绍六个主要的数据存储方式 iOS中数据存储方式&#xff08;数据持久化&#xff09; 根据要存储的数据大小、存储数据以及…

计算机毕业设计 | SpringBoot宠物店管理系统(附源码)

1&#xff0c;绪论 项目背景 我国已经成为世界第二大经济体&#xff0c;经济实力高速发展以及百姓生活水平的普遍提高&#xff0c;不断地要求企业提供更加多元化的娱乐方式&#xff0c;更加快速和方便的服务&#xff0c;因此对宠物行业也提出了更加严格的要求&#xff0c;如管…

【NI国产替代】NI‑9232,3通道,102.4 kS/s/ch,±30 V,C系列声音与振动输入模块

3通道&#xff0c;102.4 kS/s/ch&#xff0c;30 V&#xff0c;C系列声音与振动输入模块 NI‑9232可以测量来自集成电子压电(IEPE)和非IEPE传感器的信号&#xff0c;例如加速度计、转速计和接近式探针。 NI‑9232还可兼容智能TEDS传感器。\n\nNI‑9232集成了软件可选的AC/DC耦合…

Window——安装nacos

1、Git拉取项目 官方地址&#xff1a;https://nacos.io/zh-cn/ git clone https://github.com/alibaba/nacos.git2、进入项目执行命令安装&#xff08;需要maven&#xff09; Maven下载指引&#xff1a;https://blog.csdn.net/qq812457115/article/details/117451334 mvn -Prel…

JRT核心竞争力

如果说JRT业务脚本化和发部署简单和打印导出客户端都不足以抵挡Spring用的人多的优势的话。那么这一篇让DolerGet给你一个选择JRT的理由&#xff0c;借助JRT自我实现的ORM&#xff0c;JRT有能力完全把控更新数据和删除数据的口径&#xff0c;和能够准确知道哪些是热点数据&…