layout: post

title: 第四届58topcoder编程大赛

subtitle: 58ACM

catalog: true

tags:

- A* 算法

- C++

- 程序设计

问题及背景

小明是58的一名90后程序猿,除了日常接需求写代码以外,他还特别善于思考,尤其喜欢思考和58产品业务相关的问题。随着移动互联网的发展,小明推测58将来和地理位置相关的产品服务会越来越多,比如58房产下附近的商圈、58同镇下的拼车、58速运等等都是和地理位置相关产品。和地理位置相关有一个非常重要问题是:如何以最短的时间从A地去往B地。小明想到这个问题之后,很兴奋!特别是今天上班的时候车载导航又给他引到了大山子,堵车导致他上班又迟到1小时,因此他暗下决心要设计一个更加智能的路径规划算法,一方面58产品服务能用上,更重要的是他想解决大山子这个难题。可惜这个问题太难,小明单独解决有点难,希望58的同学们能够一起帮忙设计更加智能的算法,让他以后可以花费更少的时间在路上。

问题抽象

该问题可以抽象成:给定一个地图,找出从A点至B点的最优路径,使得从A点至B点所需的时间最少。为了简化问题,我们假定地图所在的坐标系为二维平面,两点之间的直线距离为欧氏距离。

1、程序输入

程序的输入包括地图和查询请求两部分。

地图由一系列的“边”组成,每条边表示地图上两点间的一条连通路径。

边的格式为:x1,y1 x2,y2 speed

x1,y1和x2,y2表示边的起点和终点在地图上的坐标,speed表示这条边上的行驶速度,并且双向行驶的速度都是一样的。所有点的坐标值x和y都是整数,单位为km(公里),取值范围为 0<=x<=100000,0<=y<=100000,两点间的速度speed为整数,单位为km/h(公里每小时),取值范围为10<=speed<=100。

查询请求表示针对该地图的查询,每个地图包含多个query,我们需要分别计算每个query所对应的最优路径。

每个query的格式为:x1,y1 x2,y2

x1,y1和x2,y2分别表示query的起点和终点在地图上的坐标。比赛给出的所有query,起点和终点一定是连通的,即起点和终点间至少存在一条连通路径。

2、程序输出

对于每个query,需要输出“路径”和“花费时间”两部分内容。

其中,路径为包含起点和终点在内的一系列点,包含从起点至终点经过的所有点的坐标;相邻两点间的距离除以对应的速度即为这两点间的花费时间,各个点之间花费时间之和即为总的花费时间,花费时间为浮点数,单位为小时。

程序输入和输出均通过文件的形式提供,各个语言提供的框架会负责读取输入文件,并将结果保存到输出文件,参赛者不需要关心相关的文件操作。

3、问题举例

输入文件:

  21
2,11 37,47 10
8,7 96,0 90
21,61 37,47 50
88,86 96,0 60
88,86 93,99 10
35,88 88,86 80
8,7 37,47 20
21,61 35,88 50
5,62 21,61 70
35,88 47,51 40
2,11 5,62 20
35,88 93,99 20
2,11 8,7 10
37,47 96,0 80
37,47 47,51 70
47,51 88,86 40
93,99 96,0 90
5,62 35,88 50
21,61 47,51 20
47,51 96,0 50
2,11 21,61 60
1
37,47 93,99

第一行表示地图的边数n,此样例地图有21条边,接下来n行分别是边的起点、终点和速度。接下来的1行表示query的数目m,此样例只有一个query,接下来m行表示每个query的起点和终点。

输出文件:

  1
2.043406 3 37,47 96,0 93,99
62

第一行表示query的结果数n和输入文件的query数是一样的,不一样会判错误。接下来n行是每一个query的答案,格式分别是耗时(单位为小时),点数m,以及m个点的坐标,其中第一个点和最后一个点必须是query中的起点和终点,最后一行是运行时间,运行时间单位是us,运行时间框架运行时会给出。

下图是上面地图和query的图形化表示。图中线段表示道路,线上的数字分别是道路的长度和平均速度,道路的长度可以根据输入文件的坐标点得到,求A到B的较短时间路线。在这里,我们展示了一条最短路线,其中红线就是最终得到的最短时间路线。比赛时,选手只要给出一条时间误差5%之内的路线即可。

(pic missing)

评价标准

比赛会提供多组地图,每组地图对应若干query。比赛会依次以各个地图及其对应的query作为输入,运行参赛者提交的程序,并判断各个query的输出结果是否正确。

对于一个特定的query,输出结果正确,必须同时满足以下两个条件:

1、花费时间正确。比赛允许花费时间有5%以内的误差,即程序计算得出花费时间与最优答案相比,只要差距在5%以内,即可认为是正确。

2、路径正确。程序计算得出的路径必须是存在于地图上的一条连通路径,且这条路径对应花费时间必须等于程序输出的花费时间。

需要说明的是,由于两点之间的最短路径可能不唯一,即起点和终点之间可能存在多条路径,它们的花费时间相同。因此,比赛并没有要求路径与标准答案完全相同,只要花费时间在允许的误差范围内,并且沿着路径能够得到对应的花费时间,就可以判定为正确。

比赛排名会综合考虑运行正确的地图数量和程序运行时间两个因素。

1、比赛首先计算运行正确的地图数量,运行正确的地图越多,排名越靠前。需要注意的是,针对某个地图的所有query都运行正确,才算这个地图运行正确;只有前一个地图运行正确的情况下才会继续运行下一个地图,如果某个地图运行错误,则后续的其他的地图均不再运行。

2、在运行正确地图数量相同的情况下,会考虑程序的运行时间,运行时间越短,排名越靠前。程序运行时间由init函数运行时间和多次运行search函数的时间之和两部分组成。程序运行时间由各语言的框架计算,参赛者不需要自己统计。

其他说明

(1)支持C++、Java、PHP和NodeJS四种编程语言。

(2)线上编译环境: cpp(gcc 4.4.7)、Java(jdk1.8.0_66)、PHP(7.1.10)、nodejs(v8.7.0)

(3)组委会提供了各个语言的程序框架,实现了读取输入文件、输出计算结果和统计运行时间等功能。每个语言的框架中都定义了一个名为Searcher的类,参赛者需要实现其中的init函数和search函数。其中,init为初始化函数,框架在读取完输入文件之后调用该函数,search为查询函数,针对每个输入文件中的每个query,框架都会调用一次search函数。提交代码时,参赛者只需要提交定义了Searcher类的文件(searcher.h/Searcher.java/Searcher.php/searcher.js)即可。

(4)比赛代码中只允许一个进程和一个线程,禁止使用多进程,禁止使用多线程,禁止程序中使用网络

(5)参赛者可以下载各个语言的框架进行本地调试,调试通过后再进行提交。在各个语言的框架里都包含一个示例性的输入文件和对应的标准答案,文件名分别为input.10.txt和standard_output.10.txt,参赛者可以使用这组示例文件验证自己程序的正确性。本地运行程序需要提供两个参数,分别表示输入文件和输出文件的路径。以C++框架为例,其编译出来的可执行文件名为a.out,则运行程序的方式为a.out input.10.txt output.10.txt,程序会从input.10.txt读取输入,并将运行结果保存在output.10.txt中。

(6)组委会将对所有最终获奖者进行代码review,利用题目、数据、网站漏洞取得排名的参赛者将取消成绩。


我的代码

框架代码及我的代码

这道求地图上两个坐标之间最短路径的题目,一般想到的是数据结构课堂上老师讲的几种方法,比如 DijkstraFloyd 算法,前者基本可以认为是一种回溯算法,适合解决单源最短路径问题, 后者可以认为是动态规划算法,适合解决两点最短路径问题,详情可以看其他人的博客或者翻书或者wiki之,本文不介绍。本篇要说的是,实际应用中,往往会使用另一种快速搜索算法--启发式搜索。

启发式搜索,最典型的就是 A*算法,其主要思想是:从起始点向终止点探索的过程中,优先选择代价(代价=已探索过路径的实际代价 和 剩余路径的预估代价)最小的路径点。这和 Dijkstra 算法的区别在于优先选择路径点的策略。

具体实现:

  1. 地图表示(点和边的标识方法,边一般用邻接表表示)
  2. 距离定义(一般用欧氏距离,本题里用的是耗时)
  3. 代价定义(实际代价 + 预估代价,实际代价如何初始化和更新,预估代价是否一成不变)
  4. 路径标记(探索过程中标识哪些点走过,哪些探索过,哪些点未探索过)
  5. 路径选择(如何优先选择代价最小的点,同时能眼观六路,此路不通时能及时调整到其他路径--优先队列)

差不多把以上几个问题想清楚了,编码写下来就差不多解决了这道题,同时对 A* 算法有大致了解了。

最新英雄榜

截止到2017年12月10日 18:46

致谢

感谢杨大师@yangyi 的精彩分享,我的代码借鉴了杨大师的 预估速度,更重要的是杨大师追求极致的精神是我等 IT 人士的典范。

第四届58topcoder编程大赛--地图路径规划的更多相关文章

  1. iOS百度地图路径规划和POI检索详细总结-b

    路径规划.png 百度地图的使用 百度地图API的导入网上说了许多坑,不过我遇到的比较少,这里就放两个比较常见的吧.坑一: 奥联WIFI_xcodeproj.png 如上图所示,在infoplist里 ...

  2. Vue 高德地图 路径规划 画点

    CDN 方式 <!--引入高德地图JSAPI --> <script src="//webapi.amap.com/maps?v=1.4.13&key=您申请的ke ...

  3. CSDN第四届在线编程大赛2014初赛:带通配符的数

    题目要求: 输入参数:参数A,含有任意个数的?的数值字符串,如:12?4,?代表一位任意数             参数B,不含?的数值字符串,长度与参数A一致输出结果:参数A比参数B大的可能数值个数 ...

  4. 【思考题】CSDN第四届在线编程大赛2014初赛:带通配符的数

    题目要求: 输入参数:参数A,含有任意个数的?的数值字符串,如:12?4,?代表一位任意数                     参数B,不含?的数值字符串,长度与参数A一致 输出结果:参数A比参数 ...

  5. Google地图路线规划

    Google地图路线规划: 需求:给定的两点之间Google地图路径规划和详情. 代码实现: //map定义省略 var directionsDisplay = new google.maps.Dir ...

  6. 基于谷歌地图的Dijkstra算法水路路径规划

    最终效果图如下: 还是图.邻接表,可以模拟出几个对象=>节点.边.路径.三个类分别如下: Node 节点: using System; using System.Collections.Gene ...

  7. [python] A*算法基于栅格地图的全局路径规划

    # 所有节点的g值并没有初始化为无穷大 # 当两个子节点的f值一样时,程序选择最先搜索到的一个作为父节点加入closed # 对相同数值的不同对待,导致不同版本的A*算法找到等长的不同路径 # 最后c ...

  8. iOS高德地图使用-搜索,路径规划

    项目中想加入地图功能,使用高德地图第三方,想要实现确定一个位置,搜索路线并且显示的方法.耗了一番功夫,总算实现了. 效果 WeChat_1462507820.jpeg 一.配置工作 1.申请key 访 ...

  9. iOS第三方地图-高德地图(导航sdk路径规划)

    @import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...

随机推荐

  1. Ajax请求携带Cookie

    目录 xhr ajax cookie跨域处理 客户端 服务端 服务端设置跨域的几种方式 方式一 重写addCorsMappings方法 方式二 对单个接口处理 方式三 @CrossOrigin注解 方 ...

  2. 重学Ajax

    什么是Ajax Asynchronous JavaScript and xml 异步的JavaScript和XML 只是一种js的应用,在无需重新加载整个网页的情况下实现部分网页的数据更新的技术.减少 ...

  3. Ubuntu修改默认Python版本,你了解多少~

    目录 1 查看Python版本 1.1 查看装有哪些版本 1.2 查看默认版本 2 修改Python默认版本 2.1 基于文件修改 2.2 基于软链接修改 1 查看Python版本 1.1 查看装有哪 ...

  4. 如何制作一个手机上的Github图床捷径(workflow)

    准备工作 github账号与绑定邮箱 建立一个仓库用于存放图片 生成github token 注意生成之后要备份以免后面要用到(页面刷新之后会看不见) 了解github上传文件的 GitHub API ...

  5. MySQL的事务机制和锁(InnoDB引擎、MVCC多版本并发控制技术)

    一.事务(数据库的事务都通用的定义) 1.1 事务定义 事务是由一步或几步数据库操作序列组成逻辑执行单元,这系列操作要么全部执行,要么全部放弃执行.事务通常以 BEGIN TRANSACTION 开始 ...

  6. HA切换失败原因分析

    1. 问题描述 redhat在进行HA切换时,需要先停止service,并释放调当前主机占有的资源,比如说IP Address和Filesystem,但今天我在验证HA切换时,发现service一直停 ...

  7. ThreadLocal源码分析与实践

    ThreadLocal是什么? ThreadLocal是一个线程内部存储类,提供线程内部存储功能,在一个ThreadLocal对象中,每一个线程都存储各自独立的数据,互不干扰 示例如下: public ...

  8. Git【常见知识点速查】

    文章更新时间:2020/06/17 一.基础知识点解析 Git工作流程 以上包括一些简单而常用的命令,但是先不关心这些,先来了解下面这4个专有名词. Workspace:工作区 Index / Sta ...

  9. Java8之日期处理

    简介 Java8除了有较大更新的 lambda. Stream ,还推出了全新的日期时间API.Java之前处理日期.日历和时间的不足之处主要有: 日期类型为可变类型,非线程安全使其应用非常受限 没有 ...

  10. vs code的使用与常用插件和技巧大全总结

    vs code的使用与常用插件和技巧大全总结 Author:3# 一个专注于web技术的80后 我不用拼过聪明人,我只需要拼过那些懒人 我就一定会超越大部分人! CSDN@ 极客小俊,CSDN官方首发 ...