ACM - 动态规划 - 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\),
第一种情况表示为
\]
第二种情况表示为
\]
综上,写出状态转移方程:
\]
我们再考虑边界的状态,边界如下
\]
状态搜索方向
使用递归做状态搜索,此方法的另一种名称叫记忆化搜索,但我个人倾向于将记忆化搜索视为动态规划的递归实现(即使用递归用状态搜索)。
程序实现
使用 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的更多相关文章
- UVa 1347 Tour
Tour Time Limit: 3000MS Memory Limit: Unknown 64bit IO Format: %lld & %llu Description Joh ...
- UVA 1347 Tour 【双调旅行商/DP】
John Doe, a skilled pilot, enjoys traveling. While on vacation, he rents a small plane and starts vi ...
- UVA - 1347 Tour(DP + 双调旅行商问题)
题意:给出按照x坐标排序的n个点,让我们求出从最左端点到最右短点然后再回来,并且经过所有点且只经过一次的最短路径. 分析:这个题目刘汝佳的算法书上也有详解(就在基础dp那一段),具体思路如下:按照题目 ...
- UVA 1347 Tour 双调TSP
TSP是NP难,但是把问题简化,到最右点之前的巡游路线只能严格向右,到最右边的点以后,返回的时候严格向左,这个问题就可以在多项式时间内求出来了. 定义状态d[i][j]表示一个人在i号点,令一个人在j ...
- UVA 1347"Tour"(经典DP)
传送门 参考资料: [1]:紫书 题意: 欧几里得距离???? 题解: AC代码: #include<bits/stdc++.h> using namespace std; ; int n ...
- Tour UVA - 1347
John Doe, a skilled pilot, enjoys traveling. While on vacation, he rents a small plane and starts vi ...
- 【UVa 1347】Tour
[Link]:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_probl ...
- UVA 1347(POJ 2677) Tour(双色欧几里德旅行商问题)
Description John Doe, a skilled pilot, enjoys traveling. While on vacation, he rents a small plane a ...
- UVa 1347 (双线程DP) Tour
题意: 平面上有n个坐标均为正数的点,按照x坐标从小到大一次给出.求一条最短路线,从最左边的点出发到最右边的点,再回到最左边的点.除了第一个和最右一个点其他点恰好只经过一次. 分析: 可以等效为两个人 ...
随机推荐
- QT:中文字符串与“常量中有字符串”报错
解决方法参照: (10条消息) Qt5.9 win7系统 中文字符串报错:常量中有字符串_Be busy living or busy dying-CSDN博客 主要是用QStringLiteral( ...
- Java:常用语句
学习时可参考: Java在线文档(中文版) Java官方文档(英文版) 0.基本 0.1.导入某个Module import java.util.List;import java.util.Array ...
- numpy.random模块用法小结
原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/9751471.html 1.np.random.random()函数参数 np.random.r ...
- Winform调用存储过程
数据表及数据准备: create table Member ( MemberId int primary key identity(1,1), MemberAccount nvarchar(20) u ...
- 矩池云上TensorBoard/TensorBoardX配置说明
Tensorflow用户使用TensorBoard 矩池云现在为带有Tensorflow的镜像默认开启了6006端口,那么只需要在租用后使用命令启动即可 tensorboard --logdir lo ...
- linux 中 /dev/null和/dev/zero的作用以及区别
在类Unix操作系统中,设备节点并不一定要对应物理设备.没有这种对应关系的设备被称之为伪设备.操作系统运用了它们实现多种多样的功能,/dev/null和/dev/zero就是这样的设备,类似的还有/d ...
- 『现学现忘』Docker基础 — 23、使用Docker安装Tomcat
目录 步骤1:搜索镜像 步骤2:下载Tomcat镜像 步骤3:运行Tomcat镜像 步骤4:本机和外网测试 步骤5:解决问题 补充:--rm选项 步骤1:搜索镜像 使用docker search命令进 ...
- CF1515H口胡
居然一下就做出来了...不知道是不是对的/fad 考虑操作的本质,首先将所有元素插入线段树中. 来依次考虑每一种操作: 区间与 注意到这个操作类似将某些节点的右儿子合并到左儿子上,而一个节点最多被合并 ...
- java案例—遍历字符串
/*案例:遍历并打印字符串 需求:键盘录入一个字符串,使用程序在控制台遍历该字符串 分析:1.使用Scanner类获取输入的字符串 2.使用public char charAt(int index)方 ...
- 阿里一面,说说你对Mysql死锁的理解
又到了金三银四的时候,大家都按耐不住内心的躁动,我在这里给大家分享下之前面试中遇到的一个知识点(死锁问题),如有不足,欢迎大佬们指点指点. 1.什么是死锁? 死锁指的是在两个或两个以上不同的进程或线程 ...