1131 Subway Map
题意:给出起点和终点,计算求出最短路径(最短路径即所经过的站点最少的),若最短路径不唯一,则选择其中换乘次数最少的一条线路。
思路:本题虽然也是求最短路径,但是此路径是不带权值的,路径长度即所经过的边数,故可以用DFS来求解,而不是用一般的Dijkstra之类的。相信若只是求最短路径,大多数人都会做,就是从起点start开始深度遍历,遍历到终点end时,与全局变量进行比较、更新。本题的关键是,更新最优路径时需要比较“换乘次数”,如何求解它呢?我是这么思考的——首先,考虑用一个二维数组int mp[maxn][maxn]来存储站点与线路的关系,如mp[6666][8432]=4,表示6666->8432是4号线,但考虑到站点编号的范围最大达到9999,也就是数组得开10000*10000,这显然是无法承受的,故选用unordered_map,令unordered_map<int,unordered_map<int,int>> mp,操作和普通的数组一样。(我发现这个unordered_map真的是非常好用,很多题目都可以用,这里不细说,有兴趣的查看文档进行学习)。那么,怎么算是“换乘”呢?假设前一个站是pre,当前站是curr,下一个站是next,若mp[pre][curr]≠mp[curr][next],说明需要一次换乘,顺序遍历路径path的所有站点,即可求出换乘次数。最后,本题的输出也是比较麻烦,但思路和求换乘次数的方法是一样的。具体请看代码,关键处都有注释。
ps.代码中尽量不要出现中文注释,因为在中文输入法下,若不小心在某一行开头输入了一个空格(难以发现),这会导致编译出错,产生“error: stray '\241' in program”的错误信息。
代码:
- #include <cstdio>
- #include <cstring>
- #include <vector>
- #include <unordered_map>
- using namespace std;
- ;
- const int Inf=0x7fffffff;
- unordered_map<int,unordered_map<int,int>> mp;//存储两站点间的地铁线,如mp[6666][8432]=4,表示6666->8432是4号线
- bool vis[maxn];//在DFS中标记结点是否已经被访问过
- vector<int> graph[maxn];//邻接表存储地铁线路图
- int k,n,m,s,e,minDistance,minTransfer;//地铁线条数,每条地铁的站点数,查询次数,查询的起点和终点,最短距离,最少换乘数
- vector<int> path,tmpPath;//path存放最优路径,tmpPath存放临时路径
- int getTransferCnt(vector<int>& path)
- {
- ;
- ];
- ;i+<path.size();i++){//注意,这里的判定是i+1<path.size()
- ];
- if(mp[pre][curr]!=mp[curr][next]) changeCnt++;
- pre=curr;//记得更新
- }
- return changeCnt;
- }
- void dfs(int s)
- {
- vis[s]=true;
- tmpPath.push_back(s);
- if(s==e){
- int tmpTransfer=getTransferCnt(tmpPath);
- < minDistance){
- minDistance=tmpPath.size()-;
- minTransfer=tmpTransfer;
- path=tmpPath;
- } == minDistance && tmpTransfer < minTransfer){
- minTransfer=tmpTransfer;
- path=tmpPath;
- }
- return;
- }
- for(auto next:graph[s]){
- if(vis[next] == true) continue;
- dfs(next);
- tmpPath.pop_back();
- vis[next]=false;
- }
- }
- void printPath(vector<int>& path)
- {
- //换乘次数为0时,只需要输出起点和终点,单独输出。这里minTransfer是全局变量,在调用该函数前已经确定
- ){
- ],b=path[path.size()-];//also b=path.back();
- printf(]][path[]],a,b);//注意,这里线路不能是mp[a][b],因为站点a、b不一定是相邻的!
- return;
- }
- ];//表示当前这条线路的起始站
- ],curr,next;
- ;i+<path.size();i++){
- curr=path[i],next=path[i+];
- if(mp[pre][curr]!=mp[curr][next]) {
- printf("Take Line#%d from %04d to %04d.\n",mp[pre][curr],start,curr);
- start=curr;//出现换乘,记得更新起始站
- }
- pre=curr;
- }
- //输出最后一次换乘至终点的线路
- printf(]][path[path.size()-]],start,path[path.size()-]);
- }
- int main()
- {
- //freopen("pat.txt","r",stdin);
- scanf("%d",&k);
- ;i<=k;i++){
- int pre,curr;
- scanf("%d%d",&n,&pre);
- ;j<n;j++){
- scanf("%d",&curr);
- graph[pre].push_back(curr);
- graph[curr].push_back(pre);
- mp[pre][curr]=mp[curr][pre]=i;
- pre=curr;
- }
- }
- scanf("%d",&m);
- while(m--){
- scanf("%d%d",&s,&e);
- //每次查询前千万记得初始化
- memset(vis,false,sizeof(vis));
- path.clear();
- tmpPath.clear();
- minDistance=Inf,minTransfer=Inf;
- dfs(s);
- printf("%d\n",minDistance);
- printPath(path);
- }
- ;
- }
1131 Subway Map的更多相关文章
- PAT甲级1131. Subway Map
PAT甲级1131. Subway Map 题意: 在大城市,地铁系统对访客总是看起来很复杂.给你一些感觉,下图显示了北京地铁的地图.现在你应该帮助人们掌握你的电脑技能!鉴于您的用户的起始位置,您的任 ...
- PAT甲级——1131 Subway Map (30 分)
可以转到我的CSDN查看同样的文章https://blog.csdn.net/weixin_44385565/article/details/89003683 1131 Subway Map (30 ...
- 1131 Subway Map DFS解法 BFS回溯!
In the big cities, the subway systems always look so complex to the visitors. To give you some sense ...
- 1131 Subway Map(30 分)
In the big cities, the subway systems always look so complex to the visitors. To give you some sense ...
- PAT 1131 Subway Map
In the big cities, the subway systems always look so complex to the visitors. To give you some sense ...
- PAT甲级1131 Subway Map【dfs】【输出方案】
题目:https://pintia.cn/problem-sets/994805342720868352/problems/994805347523346432 题意: 告诉你一个地铁线路图,站点都是 ...
- PAT 1131. Subway Map (30)
最短路. 记录一下到某个点,最后是哪辆车乘到的最短距离.换乘次数以及从哪个位置推过来的,可以开$map$记录一下. #include<map> #include<set> #i ...
- PAT_A1131#Subway Map
Source: PAT A1131 Subway Map (30 分) Description: In the big cities, the subway systems always look s ...
- 1131(★、※)Subway Map
思路:DFS遍历 #include <iostream> #include <map> #include <vector> #include <cstdio& ...
随机推荐
- KNN 算法,以及与Kmeans的简单对比
KNN与Kmeans感觉没啥联系,但是名字挺像的,就拿来一起总结一下吧. 初学者的总结. KNN是监督学习,Kmeans是无监督学习. KNN用于分类,Kmeans用于聚类. 先说KNN: 对于KNN ...
- 认证和授权(Authentication和Authorization)
什么是OAuth 如今很多网站的功能都强调彼此间的交互,因此我们需要一种简单,标准的解决方案来安全的完成应用的授权,于是,OAuth应运而生,看看官网对其的定义: An open protocol t ...
- Ajax基础(三)--eval的使用
eval的使用: 1.定义和用法 计算某个字符串,并执行其中的js代码 eval(string) string必须,含有表达式或执行语句 string有返回值的话 2.实例 2.1 字符串上该用eva ...
- JSON字符串与JSON对象的互相转换
比如工作中遇到的app强制退出功能的参数问题 首先定义一个JSON字符串 objectStr : String value=UUID.randomUUID().toString();SimpleDat ...
- 个人作业4——alpha阶段个人小结
一.个人总结 在alpha 结束之后, 每位同学写一篇个人博客, 总结自己的alpha 过程: 请用自我评价表:http://www.cnblogs.com/xinz/p/3852177.html 有 ...
- winform 中 MessageBox 用法大全
(转自:http://blog.csdn.net/xuenzhen123/article/details/4808005) MessageBox.Show()共有21中重载方法.现将其常见用法总结如下 ...
- 交叉编译工具链介绍《Building Embedded Linux Systems》
1.前言 配置和编译一个合适的GNU工具链是相对复杂的并且需要很精细的操作,包括你需要对不同软件库之间的依赖关系.它们的各自的任务,不同软件库版本情况都有比较好的了解,编译工具链是一个乏味的工作. 2 ...
- 原创:项目管理的理论与实践 讲座的PPT
业余时间做的两个PPT,曾经给公司同事讲过,PPT内容毕竟还是不够全面,如果有不清楚的地方,欢迎提问 项目管理的理论与实践 虚拟案例-超市管理系统
- ubuntu1604-server上安装virtualbox+phpvirtualbox
1.需要安装phpvirtualbox版本与virtualbox的版本一致,比如phpvirtual5.0.x,需要对应virtualbox 5.0.x 2.需要安装的软件有apache2.php.l ...
- let防止变量声明提前
let可以解决原来js中,一个函数中变量混乱的问题,因为以前var 定义的变量时, {}是不能限制变量作用域的. "use strict"; +function(){ var t= ...