P1523 旅行商简化版
P1523 旅行商简化版
题目背景
欧几里德旅行商(Euclidean Traveling Salesman)问题也就是货郎担问题一直是困扰全世界数学家、计算机学家的著名问题。现有的算法都没有办法在确定型机器上在多项式时间内求出最优解,但是有办法在多项式时间内求出一个较优解。
为了简化问题,而且保证能在多项式时间内求出最优解,J.L.Bentley提出了一种叫做bitonic tour的哈密尔顿环游。它的要求是任意两点(a,b)之间的相互到达的代价dist(a,b)=dist(b,a)且任意两点之间可以相互到达,并且环游的路线只能是从最西端单向到最东端,再单项返回最西端,并且是一个哈密尔顿回路。
题目描述
著名的NPC难题的简化版本
现在笛卡尔平面上有n(n<=1000)个点,每个点的坐标为(x,y)(-2^31<x,y<2^31,且为整数),任意两点之间相互到达的代价为这两点的欧几里德距离,现要你编程求出最短bitonic tour。
输入输出格式
输入格式:
第一行一个整数n
接下来n行,每行两个整数x,y,表示某个点的坐标。
输入中保证没有重复的两点,
保证最西端和最东端都只有一个点。
输出格式:
一行,即最短回路的长度,保留2位小数。
输入输出样例
7
0 6
1 0
2 3
5 4
6 1
7 5
8 2
25.58
分析:
【1】题意:旅行商问题,不过要求只能单向走,就是有n个地方,要求从西往东,到最东面的地方,在从东往西返回,经过每个点一次,求最短路径
【2】分析:由于有了方向的限制,这题不再是NP难题,我们可以假设有两个人一起从西往东走,走过的点不能重复,这样就有f[ i ][ j ]表示第一个人走到i,第二个人走到j 的最短路径,要求i<j,且0到j的点都被经过了,这样很容易想到,j+1的点不是被第一个人走,就是被第二个人走,所以有转移方程f[ i ][ j+1]=min{ f[ i ] [ j ]+d[ j ] [ j +1] } f[ j ] [ j+1 ]=min{ f[ i ][ j ]+d[ i ][ j+1 ] },第一个转移方程很容易理解,第二个方程可以这么理解,两个人可以指前面一个人,和后面一个人,当后面的人走到前面,当然就对换过来了,不影响结果
【3】最后,预处理f[ 0 ][ 1]还有扫描 一遍答案就行了,这题算是一类DP吧,思路挺有启发性的
#include <cmath>
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int mm=;
struct data
{
double x,y;
}g[mm];
double d[mm][mm],f[mm][mm];
int i,j,k,n;
bool cmp(const data &a,const data &b)
{
return a.x<b.x;
}
double mdis(const data &a, const data &b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int main()
{
scanf("%d",&n);
for(i=;i<n;++i)
scanf("%lf%lf",&g[i].x,&g[i].y);
sort(g,g+n,cmp);
for(i=;i<n;++i)
for(j=i+;j<n;++j)
{
d[i][j]=mdis(g[i],g[j]);
f[i][j]=1e30;
}
f[][]=d[][];
for(i=;i<n;++i)
for(j=i+;j<n;++j)
{
f[i][j+]=min(f[i][j+],f[i][j]+d[j][j+]);
f[j][j+]=min(f[j][j+],f[i][j]+d[i][j+]);
}
double ans=1e30;
for(j=;j<n-;++j)
ans=min(ans,f[j][n-]+d[j][n-]);
printf("%.2lf\n",ans);
return ;
}
2、填表法
代码是从后往前填表
遍历一整个图, 从开始位置走到末尾,再走回开始位置,并且不能重复;
由于题目并没有对输入数据按X从小到大排序,所以先排序,然后预处理出每两个点之间的欧几里得距离。
f(i,j)表示 从 1->max(i,j) 已经全部遍历切没有重复的最短路;
那么可知F(i , j) = F(j , i); 于是就规定 i > j;
如果 i = n - 1; 那么就强行将j跳到末尾位置;f(i, j) = dis(i, n) + dis(j, n);
其余可知 f(i,j) = max ( f(i+1, j) + dis(i, i +1), f(i+1, i) + dis(j, i+1)) 原本应写成f(i, i+1), 但由于规定所以写成这样;
最终状态为f(2, 1);
接着就是naive的输出啦;
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
typedef long long Lovelive;
using namespace std; const int maxn = + ;
int n;
struct Node {
double x, y;
}node[maxn];
double dis[maxn][maxn], f[maxn][maxn]; bool cmp(Node a, Node b) {
return a.x < b.x;
} int main() {
scanf("%d",&n);
for(int i = ; i <= n; i++) scanf("%lf%lf",&node[i].x,&node[i].y);
sort(node+, node+n+, cmp);
for(int i = ; i <= n; i++)
for(int j = ; j <= n; j++)
dis[i][j] = sqrt((node[i].x-node[j].x)*(node[i].x-node[j].x) + (node[i].y-node[j].y)*(node[i].y-node[j].y)); for(int i = n-; i >= ; i--)
for(int j = ; j < i; j++)
if(i == n-) f[i][j] = dis[i][n] + dis[j][n];
else f[i][j] = min (f[i+][j] + dis[i][i+], f[i+][i] + dis[j][i+]);
printf("%.2lf",f[][] + dis[][]);
return ;
}
P1523 旅行商简化版的更多相关文章
- 洛谷P1523 旅行商简化版(DP)
题目: P1523 旅行商简化版 解析 可以看做是两个人同时从西往东走,经过不一样的点,走到最东头的方案数 设\(f[i][j]\)表示一个人走到i,一个人走到j的最短距离(\(i<j\)) 第 ...
- [vijos P1014] 旅行商简化版
昨天早上上课讲旅行商问题,有点难,这周抽空把3^n的算法码码看.不过这个简化版已经够折腾人了. 其一不看解析不知道这是双进程动态规划,不过我看的解析停留在f[i,j]表示第一个人走到i.第二个人走到j ...
- vijosP1014 旅行商简化版
vijosP1014 旅行商简化版 链接:https://vijos.org/p/1014 [思路] 双线DP. 设ab,ab同时走.用d[i][j]表示ab所处结点i.j,且定义i>j,则有转 ...
- 洛谷【P1523】旅行商的背包(算法导论 15-1) 题解
P1523 旅行商简化版 题目背景 欧几里德旅行商\((Euclidean Traveling Salesman)\)问题也就是货郎担问题一直是困扰全世界数学家.计算机学家的著名问题.现有的算法都没有 ...
- 【C#代码实战】群蚁算法理论与实践全攻略——旅行商等路径优化问题的新方法
若干年前读研的时候,学院有一个教授,专门做群蚁算法的,很厉害,偶尔了解了一点点.感觉也是生物智能的一个体现,和遗传算法.神经网络有异曲同工之妙.只不过当时没有实际需求学习,所以没去研究.最近有一个这样 ...
- 洛谷P1782 旅行商的背包[多重背包]
题目描述 小S坚信任何问题都可以在多项式时间内解决,于是他准备亲自去当一回旅行商.在出发之前,他购进了一些物品.这些物品共有n种,第i种体积为Vi,价值为Wi,共有Di件.他的背包体积是C.怎样装才能 ...
- 2016全国研究生数学建模A题多无人机协同任务规划——基于分布式协同多旅行商MTSP遗传算法
MTSP问题是指:有Ⅳ个城市,要求旅行商到达每个城市各一次,且仅一次,并[旦 1到起点,且要求旅行路线最短.而多旅行商问题M个旅行商从同一个城市(或多个城市)出发.分羽走一条旅路线,且总路程缀短.有关 ...
- Bzoj3352 [ioi2009]旅行商
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 89 Solved: 36 Description 旅行商认定如何优化旅行路线是一个非常棘手的计算问题 ...
- hdu 4281 Judges' response(多旅行商&DP)
Judges' response Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
随机推荐
- paper 141:some paper with ComputerCV、MachineLearning[转]
copy from:http://blog.csdn.net/zouxy09/article/details/8550952 一.特征提取Feature Extraction: · S ...
- 使用html5进行视频播放
一直以来网页大多是使用 flash 来播放视频.在目前唱衰 flash 的环境下,HTML5 为我们带来了一个网页内视频播放的解决方案—— <video>标签. 在HTML5 中,可以通过 ...
- cms网站模板收集
Dedecms模板 1.魔客吧 ----- dedecms .wordpress .discuz.shopnc.ecshop等模板都有 eg: html5绿色响应式企业网页模板 2.绘艺素材 -- ...
- jQuery Mobile 自定义导航条图标
1.jQuery Mobile 自定义导航条图标
- C#中Json转换主要使用的几种方法!
这篇主要介绍2.4.第三种方法使用的比较局限,所以我没有深入学习. 第二种方法 我使用比较多的方式,这个方法是.NET内置的,使用起来比较方便 A.利用serializer获取json的泛型对象 利用 ...
- LInux终端中Ctrl+S卡死
因为初学Linux,在vim中写东西是总是喜欢按Ctrl+s来保存内容导致终端突然卡主,然后上网查资料发现了Ctrl+s 暂停屏幕输出[锁住终端]而对应的按键是Ctrl+q 恢复屏幕输出[解锁终端]
- IDEA如何import一个新的项目
首先解决依赖问题:打开pom.xml 2.打开File->setting 将里面的User setting file位置找到,放上settings.xml(注意要打开,将第一行位置改一下) 3. ...
- ZABBIX 忘记登录密码
ZABBIX 忘记登录密码 摘要 有些童鞋会忘记zabbix的登陆密码,今天给大家写一篇找回登陆密码~ ZABBIX 忘记登录密码 zabbix 刚刚在群里吹牛逼,由于账号比较多,脑子容易 ...
- SpringBoot传递单一参数时@RequestParam和@RequestBody的区
用SpringBoot框架做项目时,经常需要前端给后端传递参数,如果需要多条参数,通常的做法是把这些参数封装为一个对象来传递,前端用POST方式调用.但有时会遇到后端只需要一条参数(比如一个Strin ...
- sed以及awk
一.sed sed是一种流编辑器,它一次处理一行内容.处理时,把当前处理的行存储在临时 缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的 内容,处理完成后,把缓 ...