学校“数据结构”课程Project—扩展功能(自主设计)

目录

一、设想功能描述

想法缘起

目标功能

二、问题抽象

三、算法设计和优化

1. 易想的朴素搜索 / dp

搜索想法

动态规划(dp)想法

2. 思考与优化

四、算法实现

五、结果示例

附:使用的地图API


一、设想功能描述

想法缘起

  • OSM 导出的地图数据中有 “amenity”(便民设施)点,并在 <tag k="amenity" v="..."/> 中标记了每个 amenity 的具体类型,比如:fast_food, pub, toilets……

  • 而人们在路途或旅途中,常常关注最近的某种类型(常为 amenity,如卫生间、停车车场)的最近处,而尚未明确目的地。从而容易想到去设计一个扩展功能:给定 amenity,查询距离当前点最近的该类的点显然,这个问题仍用 Dijkstra 求单源最短路即可。

  • 然而,有时人们想连续去多个便民点,比如:先去停车场停车再去吃饭,最后逛逛周边的公园等等。为了提高效率与体验,很可能需要一个总路程最短的方案,这就是该 “扩展功能” 考虑的问题。

目标功能

★ 用户给定当前位置,并指定一个 amenity 种类的顺序。求出最短路线,并呈现在地图上。

二、问题抽象

地图上有某些点带有颜色。给出起点 s 与颜色序列 [c_1,c_2,\dots,c_n]尽可能快地求出一条以 s 为起点的最短路线 P,要求其依次经过颜色为 c_1,c_2,\dots,c_n 的点。

存在数据约束与特征:|C_i|\le 400,其中 C_ii 颜色点集,此外,各种颜色的点大致均匀分布。

三、算法设计和优化

1. 易想的朴素搜索 / dp

搜索想法

直接以每个 c_i 为阶段,进行深度优先搜索(DFS),这部分时间复杂度已经有 O(\Pi_{i=1}^n|C_i|),虽然可以进行剪枝,即当前搜素的长度 cur 超过搜到的最短长度 res,就直接 return,但光这样时间复杂度不变的。

动态规划(dp)想法

以每个 c_i 为阶段设计 dp,易得状态转移方程类似如下形式:

f[i][u]=\max_{v\in C_{i-1}}\{f[i-1][v]+dis(v,u)\},u\in C_i

然而,显然其时间复杂度是同搜索的,而且还很难剪枝,所以比搜索更差。

此外,还要计算中间相邻颜色两点的最短路,从而全求出来的时间复杂度应比上面更大,空间复杂度亦大。

2. 思考与优化

直观地,最终答案的路线几乎不可能 “兜得很远”,这启发我们优化搜索顺序。对于每个 u\in C_i,我们考虑先走到离最近的 v_1\in C_{i+1} 搜索下去,回溯后再搜次近的 v_2\in C_{i+1}……可以想象这样搜出来的前几条路已经得到或较接近最终答案。进一步来看,又因为各种颜色的点大致均匀分布,所以这样的剪枝效果一定是非常显著的。

不过,如何求出搜 v\in C 的顺序?其实我们完全不必先预处理出最短路然后排序。注意到 Dijkstra 的最短路算法就是按照距离由到达的顺序得到 “确定点” 的。所以,我们把 Dijkstra 算法 “嵌入” 搜索框架之中,从当前 u\in C_i 做 Dijkstra,遍历到一个下一颜色的 v\in C_{i+1},我们就从 v 递归进行搜索。这样相当于又解决了花大代价计算最短路的问题。

总之,本问题基于搜索的大框架,而其内部融入 Dijkstra,每个结点处的下一个点通过 Dijkstra 确定,当前搜索路上的每个点都保留了一个 Dijkstra 状态。

四、算法实现

关键在于构建搜索的代码,尤其是解决 “每一层” 都在做 Dijkstra 带来的问题

原始 Dijkstra 只有一个答案数组 d[MAXN] ,这里我们显然需要多个,不过我们若开 n 个这样的数组,内存开销较大,且可能不易扩展。注意到 {d[u], u} 保留在原始 Dijkstra 的 std::priority_queue 中,我们可以std::set 代替这个 std::priority_queue,既可以取出最小值,又存下来当前有用的 {d[u], u} 且能 std::find 得到 {d[v], v},而 vis 数组可用 std::unordered_set 代替

这样,我们相当于仅在搜索路上开 C++ 的容器,空间开销显著减小而并未增大过多增加时间常数,且易于扩展。

void DFS(int s, int x, double cur) {
    if (x == Ord.size()) { // ... }
    set<pair<double, int>> d; d.insert({0.0, s});
    unordered_set<int> vis;
    while (d.size()) {
        int u = d.begin()->second;
        double dis = d.begin()->first;
        if (cur + dis > ans) return;
​
        d.erase(d.begin());
        if (vis.find(u) != vis.end()) continue;
        vis.insert(u);
        auto itt = M.p[u].Ames.find(Ord[x]);
        if (itt != M.p[u].Ames.end()) {
            curOrd.push_back(u);
            DFS(u, x+1, cur+dis);
            curOrd.pop_back();
        }
​
        for (int e = M.head[u]; e; e = M.nxt[e]) {
            // ...
            auto it = d.upper_bound({-1.0, v});
            if (it==d.end() || it->second!=v || dis+w<it->first) d.insert({dis+w, v});
        }
    }
}

五、结果示例

  • n=6:起点在徐家汇一带,(较为随意地)指定下面 6 个 Amenity Type 的顺序:

附:使用的地图API

        基于 Leaflet.js 库的 Python 交互式地图包 Folium

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【昕宝爸爸小模块】什么是POI,为什么它会导致内存溢出?

➡️博客首页 https://blog.csdn.net/Java_Yangxiaoyuan 欢迎优秀的你&#x1f44d;点赞、&#x1f5c2;️收藏、加❤️关注哦。 本文章CSDN首发&#xff0c;欢迎转载&#xff0c;要注明出处哦&#xff01; 先感谢优秀的你能认真的看完本文&…

缓存问题 | 缓存穿透,缓存击穿,缓存雪崩

缓存穿透 关键字&#xff1a;强调缓存和数据库都没有数据并发访问 缓存穿透是指数据库和缓存都没有的数据&#xff0c;每次都要经过缓存去访问数据库&#xff0c;大量的请求有可能导致DB宕机。 应对策略&#xff1a; 使用布隆过滤器&#xff08;Bloom Filter&#xff09;&am…

react中优化类名写法(类似与vue的动态class对象方式)

安装和引入方式 npm install classnamesimport classNames form classsnames//render 方法中&#xff0c;需要动态className的地方直接参照上图使用

基于 java+springboot+mybatis电影售票网站管理系统前台+后台设计和实现

基于 javaspringbootmybatis电影售票网站管理系统前台后台设计和实现 &#x1f345; 作者主页 央顺技术团队 &#x1f345; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; &#x1f345; 文末获取源码联系方式 &#x1f4dd; &#x1f345; 查看下方微信号获取联系方式 承…

数学建模-------误差来源以及误差分析

绝对误差&#xff1a;精确值-近似值&#xff1b; 举个例子&#xff1a;从A到B&#xff0c;应该有73千米&#xff0c;但是我们近似成了70千米&#xff1b;从C到D&#xff0c;应该是1373千米&#xff0c;我们近似成了1370千米&#xff0c;如果使用绝对误差&#xff0c;结果都是3…

YOLOv8训练自己的数据集,通过LabelImg

记录下labelImg标注数据到YOLOv8训练的过程,其中容易遇到labelImg的坑 数据集处理 首先在mydata下创建4个文件夹 images文件夹下存放着所有的图片&#xff0c;包括训练集和测试集等。后续会根据代码进行划分。 json文件夹里存放的是labelImg标注的所有数据。需要注意的是&…

【王道数据结构】【chapter2线性表】【P43t15】

单链表有环&#xff0c;是指单链表的最后一个节点的指针指向了链表中的某个结点&#xff08;通常单链表的最后一个节点的指针域是空的&#xff09;。试编写算法判断单链表是否存在环。 #include <iostream>typedef struct node{int data;node* next; }node,*list;list I…

java web 职位推荐系系统Myeclipse开发mysql数据库协同过滤算法java编程计算机网页项目

一、源码特点 java Web职位推荐系统是一套完善的java web信息管理系统 &#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0…

AWTK 开源串口屏开发(8) - 系统设置

AWTK 开源串口屏开发 - 系统设置 系统设置只是一个普通应用程序&#xff0c;不过它会用 默认模型 中一些内置的属性和命令&#xff0c;所以这里专门来介绍一下。 1. 功能 在这个例子会用到 默认模型 中一些下列内置的属性和命令&#xff1a; 内置属性 属性类型说明rtc_yea…

基于深度学习的狗狗类别检测

探索狗狗识别技术 引言1. 数据集介绍1.1 语境1.2 内容1.3 致谢 2. 项目背景与意义3. 项目实现流程3.1 数据处理与准备3.2 环境准备与工具安装3.3 模型配置与训练3.4 模型评估与预测3.5 模型推理与部署 4. 总结 服务 引言 随着人工智能技术的不断发展&#xff0c;图像识别已成为…

详解矩阵的LDU分解

目录 一. 矩阵分解 二. 解方程 三. 例题说明 四. 矩阵的LDU分解 五. 矩阵三角分解的唯一性 一. 矩阵分解 其实我们可以把一个线性系统&#xff08;Linear System&#xff09;看成两个三角系统&#xff08;Triangular Systems&#xff09;&#xff0c;本文章将解释为什么可…

Ubuntu 22.04 apt 安装 ros1 ros Noetic Ninjemys

众所周知 ros2还有很多功能没有移植&#xff0c;而ros1官方不再支持 ubuntu 20.04 之后的版本。另一方面Ubuntu 22.04 更新了很多对新硬件的驱动&#xff0c;有更好的兼容性和体验&#xff0c;这就变的很纠结。 如果想在 22.04 使用最新版本的 ros noetic 只有自己编译一个办法…

2024不可不会的StableDiffusion(二)

1. 引言 这是我关于StableDiffusion学习系列的第二篇文章&#xff0c;如果第一篇你还没有阅读&#xff0c;强烈推荐大家翻看前篇内容。在本文中&#xff0c;我们将学习构成StableDiffusion的各个基础组件&#xff0c;并针对每个组件的功能进行阐述。 闲话少说&#xff0c;我们…

JavaEE 网络编程

JavaEE 网络编程 文章目录 JavaEE 网络编程引子1. 网络编程-相关概念1.1 基本概念1.2 发送端和接收端1.3 请求和响应1.4 客户端和服务端 2. Socket 套接字2.1 数据包套接字通信模型2.2 流套接字通信模型2.3 Socket编程注意事项 3. UDP数据报套接字编程3.1 DatagramSocket3.2 Da…

matplotlib多个子图共用一个colorbar

文章目录 colorbar共用colorbar布局colorbar colorbar matplotlib默认提供的功能是&#xff0c;在多个子图中分别生成colorbar&#xff0c;例如 import numpy as np import matplotlib.pyplot as pltfig plt.figure() for i in range(2):ax fig.add_subplot(2,1,i1)ax plt…

掌握HTTP协议:GET和POST请求之间的关键差异

掌握HTTP协议&#xff1a;GET和POST请求之间的关键差异 HTTP&#xff08;Hypertext Transfer Protocol&#xff09;是用于在Web浏览器和服务器之间传递信息的协议。在HTTP中&#xff0c;GET请求和POST请求是两种最基本的请求方法。HTTP的底层是TCP/IP&#xff0c;所以GET和POST…

数据库设计的一些原则

文章目录 数据库设计原则表之间的关系一对一关系&#xff08;了解&#xff09;一对多&#xff08;多对一&#xff09;多对多联合主键和复合主键 数据库设计准则-范式1、函数依赖2、完全函数依赖3、部分函数依赖4、传递函数依赖5、码 第一范式第二范式第三范式第三范式 数据库设…

Go 从标准输入读取数据

fmt.Scan系列 fmt.Scan函数定义如下&#xff1a; // Scan scans text read from standard input, storing successive space-separated values into successive arguments. // Newlines count as space. // It returns the number of items successfully scanned. // If tha…

JZ15 二进制中1的个数(牛客)(C语言)

个人博客主页&#xff1a;https://blog.csdn.net/2301_79293429?typeblog 专栏&#xff1a;https://blog.csdn.net/2301_79293429/category_12545690.html 该题我为笨办法,与题解不同,如有疑问和见解,欢迎大家在评论区提出 题目链接: 二进制中1的个数_牛客题霸_牛客网 (now…

XSS靶场练习(pikachu和dvwa)

Pikachu靶场xss练习 反射型xss(get) 输入123发现被直接插入到了html中&#xff0c;而且输入框有字符长度限制 在url中构造payload:<script>alert(123)</script> 反射型xss(post) 查看源码发现登录界面没有任何机会&#xff1b;登录后输入123发现和xss(get)写入位…