UVA 1347 Tour

题解

题目大意:有 \(n\) 个点,给出点的 \(x\)、\(y\) 坐标。找出一条经过所有点一次的回路,从最左边的点出发,严格向右走,到达最右点再严格向左,回到最左点。问最短路径距离是多少?

这题原始的问法是不加严格向左严格向右的边界条件,也即著名的旅行商问题(TSP 问题),原问题已经被证明是一个 NP 难的问题。但在此题的限制条件下,我们可以在多项式时间里解决该问题。

我们可以试着从最左边往右走,当准备经过一个点时,它只有两种可能,一是从左往右时经过该点,二是从右往左经过该点。我们可以直接将问题等价为:两个人都从最左边往最右边行走(\(x\) 坐标严格大),每个点都被经过且仅被一个人经过(除起点和终点,起点和终点被各自经过一次),使两条路径加和最短。

显然同一个 \(x\) 坐标的点的数量最多两个,如果有至少三个点会使得至少一个点不能被这两人经过(路径要求 \(x\) 坐标严格大),此时必定不能形成回路。

我们使用动态规划求解,令 \(dp[i][j]\) 表示点 \(1 \sim max(i,j)\) 全部走过,且两个人的当前位置分别是点 \(i\) 和 \(j\),还需要走多长的距离到达最右边(终点)。

状态转移方程

考虑状态 \(dp[i][j]\),由于此时点 \(1 \sim max(i,j)\) 全部走过,因此要达到此状态,只有两种可能,点 \(max(i,j)+1\) 由第一个人走,点 \(max(i,j)+1\) 由第二个人走。

用 \(dist(m_1, m_2)\) 函数表示点 \(m_1\) 到 点 \(m_2\) 的欧几里得距离。此时若 \(i > j\),

第一种情况表示为

\[dp[i][j] = dp[i+1][j] + dist(i, i+1)
\]

第二种情况表示为

\[dp[i][j] = dp[i][i+1] + dist(i+1, j)
\]

综上,写出状态转移方程:

\[dp[i][j] = \min \left( dp[i+1][j] + dist(i, i+1), dp[i+1][i] + dist(j, i+1) \right)
\]

我们再考虑边界的状态,边界如下

\[dp[n-1][j] = dist(n-1, n) + dist(n, j)
\]

状态搜索方向

使用递归做状态搜索,此方法的另一种名称叫记忆化搜索,但我个人倾向于将记忆化搜索视为动态规划的递归实现(即使用递归用状态搜索)。

程序实现

使用 C++ 实现算法。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#include<queue>
#include<cmath>
#define PII pair<int, int>
#define INF 0x3f3f3f3f
using namespace std; struct point
{
double x; // x 坐标
double y; // y 坐标
}ps[1005]; double dp[1005][1005]; double dist(int i, int j)
{
return sqrt((ps[i].x - ps[j].x) * (ps[i].x - ps[j].x) +
(ps[i].y - ps[j].y) * (ps[i].y - ps[j].y));
} double fun(int i, int j)
{
if (dp[i][j] > 0)
return dp[i][j];
return dp[i][j] = min(fun(i + 1, j) + dist(i, i + 1),
fun(i + 1, i) + dist(j, i + 1));
} int main()
{
int N = 1;
while (cin >> N) {
for (int i = 1; i <= N; ++i)
cin >> ps[i].x >> ps[i].y;
memset(dp, 0, sizeof(dp));
for (int j = 1; j < N - 1; j++)
dp[N - 1][j] = dist(N - 1, N) + dist(j, N);
double ans = fun(1, 1);
printf("%.2f\n", ans);
}
return 0;
}

ACM - 动态规划 - UVA 1347 Tour的更多相关文章

  1. UVa 1347 Tour

    Tour Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Description   Joh ...

  2. UVA 1347 Tour 【双调旅行商/DP】

    John Doe, a skilled pilot, enjoys traveling. While on vacation, he rents a small plane and starts vi ...

  3. UVA - 1347 Tour(DP + 双调旅行商问题)

    题意:给出按照x坐标排序的n个点,让我们求出从最左端点到最右短点然后再回来,并且经过所有点且只经过一次的最短路径. 分析:这个题目刘汝佳的算法书上也有详解(就在基础dp那一段),具体思路如下:按照题目 ...

  4. UVA 1347 Tour 双调TSP

    TSP是NP难,但是把问题简化,到最右点之前的巡游路线只能严格向右,到最右边的点以后,返回的时候严格向左,这个问题就可以在多项式时间内求出来了. 定义状态d[i][j]表示一个人在i号点,令一个人在j ...

  5. UVA 1347"Tour"(经典DP)

    传送门 参考资料: [1]:紫书 题意: 欧几里得距离???? 题解: AC代码: #include<bits/stdc++.h> using namespace std; ; int n ...

  6. Tour UVA - 1347

    John Doe, a skilled pilot, enjoys traveling. While on vacation, he rents a small plane and starts vi ...

  7. 【UVa 1347】Tour

    [Link]:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_probl ...

  8. UVA 1347(POJ 2677) Tour(双色欧几里德旅行商问题)

    Description John Doe, a skilled pilot, enjoys traveling. While on vacation, he rents a small plane a ...

  9. UVa 1347 (双线程DP) Tour

    题意: 平面上有n个坐标均为正数的点,按照x坐标从小到大一次给出.求一条最短路线,从最左边的点出发到最右边的点,再回到最左边的点.除了第一个和最右一个点其他点恰好只经过一次. 分析: 可以等效为两个人 ...

随机推荐

  1. 国产化之银河麒麟安装达梦数据库DM8

    背景 某个项目需要实现基础软件全部国产化,其中操作系统指定银河麒麟,数据库使用DM8. 虽然在之前的文章中已经成功模拟国产飞腾处理器,但是运行效率不高,所以这里的银河麒麟操作系统还是运行在x64平台上 ...

  2. feign服务中调用,传递token

    默认spring-boot 微服务中 用feign来做服务间调用,是不会携带token传递的.为了能让服务间调用的时候带上token,需要进行配置,增强resTemplate   1.先实现请求拦截器 ...

  3. Linux 磁盘inode字节数占满的问题

    查看ext系列文件系统的信息 #dumpe2fs /dev/sdc1 Inode count: 65536 inode号数量 Block count: 262144 块数量 Reserved bloc ...

  4. 二进制部署1.23.4版本k8s集群-5-部署Master节点服务

    1.安装Docker 在21.22.200三台机器上安装Docker.安装命令: 在21.22.200三台主机上部署Docker. ~]# curl -fsSL https://get.docker. ...

  5. egg-multipart + el-upload 实现带参图片上传至阿里云OSS

    egg-multipart有两种模式:file和stream el-upload参数传递有两种方式:利用自带参数data和手动添加参数 egg-multipart介绍 一.file 模式下的带参传递 ...

  6. BBS项目分布搭建二(个人站点相关)

    BBS项目分布搭建二 1. 首页详情补充 # 在home.html文件中 body标签内补充: <div class="container-fluid"> <di ...

  7. 如何取消 UIView 动画?

    原文链接 最近项目中有一个需求是需要手动点击相机对焦,这里由于相机对焦部分需要一个类似于系统对焦框一样的缩放动画,同时动画时长为0.3秒,因此这里就有一个很普遍的需求,如果用户在0.3秒内继续点击对焦 ...

  8. 手把手教你写一个SpringMVC框架

    一.介绍 在日常的 web 开发中,熟悉 java 的同学一定知道,Spring MVC 可以说是目前最流行的框架,之所以如此的流行,原因很简单:编程简洁.上手简单! 我记得刚开始入行的时候,最先接触 ...

  9. Python函数-5 生成器

    生成器有时候,序列或集合内的元素的个数非常巨大,如果全制造出来并放入内存,对计算机的压力是非常大的.比如,假设需要获取一个10**20次方如此巨大的数据序列,把每一个数都生成出来,并放在一个内存的列表 ...

  10. sqlserver 中,如何将getdate()时间的时分秒固定为00:00:00或者忽略不要

    在使用getdate()时,时间会实时刷新,那么我们就要再查询的时候就需要精确到毫秒后三位,非常难受,那么为了解决这个问题我们可以通过以下几种方法进行固定或者去掉毫秒 1.将毫秒固定为00:00:00 ...