带信号灯的最短路dijkstra问题(阿里巴巴2018校园招聘算法题)
题目描述
现在城市有N个路口,每个路口有自己的编号,从0到N-1,每个路口还有自己的交通控制信号,例如0,3表示0号路口的交通信号每3个时刻变化一次,即0到3时刻0号路口允许通过,3到6时刻不允许通过,而6到9时刻又允许通过;以此类推,所有路口的允许通行都从时刻0开始。同时城市中存在M条道路将这N个路口相连接起来,确保从一个路口到另一个路口都可达,每条路由两个端点加上通行所需要的时间表示。现在给定起始路口和目的路口,从0时刻出发,请问最快能在什么时刻到达?
思路
由于Dijkstra算法每一步计算的都是从初始点到达各点之间的最短距离,这使得我们能够很容易计算在有信号灯的情况下通过路口需要在路口等待信号灯的时间,因此加入信号灯约束之后可对Dijkstra算法做如下改动即可:给定一个网络有节点集V,有向边集E,权重矩阵W,起点和终点分别为s和t,各路口信号灯变化周期为time。
初始化:标记节点集合为M,仅包含s;M中节点到V-M中节点的距离设为无穷大,初始节点到各节点的最短时间径记为dis,dis[s]=0;
step1:计算从M中各节点到V-M中各节点通行时间最小值,找到V-M中对应最短通行时间的节点并将其添加为标记节点,对应的最短通行时间为找到的最小值。
松弛:dis[j]= min{dis[j], dis[i] + W[i, j] + wait[i, j]},其中wait为从i路口到通过j路口需要等待信号灯时间,计算方法为:如果j为终节点则等待时间为0[不用通过,到达即可]。
否则计算wait= (dis[i] + W[i, j])%(2*time[j]),如果wait小于time[j]则无需等待直接通过,否则需等待2*time[j]-wait。
step2:检查标记节点中是否包含t,如果是则终止,否则进入step1。
输入:
节点总数,节点的等待时间,边数,两个路口间的通行时间,s,t
9
0,3
1,5
2,7
3,3
4,5
5,7
6,9
7,3
8,5
14
0,1,4
0,7,8
1,2,8
1,7,11
2,3,7
2,5,4
2,8,2
3,4,9
3,5,14
4,5,10
5,6,2
6,8,6
6,7,1
7,8,7
0,4
输出:28
程序:
#include<stdio.h>
#include<string.h>
#include<string>
#include<iostream>
#include<algorithm>
using namespace std; #define ms(x, y) memset(x, y, sizeof(x))
#define mc(x, y) memcpy(x, y, sizeof(x))
const int inf = 0x3f3f3f3f;
const int N = 50;
int tm[N], dis[N], road[N][N];
bool vis[N];
int n; int dijkstra(int s, int t)
{
ms(vis, false);
ms(dis, inf);
dis[s] = 0;
while (true)
{
int v = -1;
for (int i = 0; i < n; i++)
if (!vis[i] && (v == -1 || dis[v]>dis[i])) v = i;
vis[v] = true;
for (int i = 0; i < n; i++)
{
if (!vis[i])
{
int wait = (dis[v] + road[v][i]) % (tm[i] * 2);
if (wait < tm[i])wait = 0; //不需等待
else wait = tm[i] * 2 - wait; //等待时间
if (i == t) wait = 0; //如果遇到终节点则无需等待
if (dis[i] > dis[v] + road[v][i] + wait) // 松弛操作的变型
dis[i] = dis[v] + road[v][i] + wait;
}
}
if (v == t)break; // 终节点退出
}
return dis[t];
} int main()
{
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
int pos, time;
scanf("%d,%d", &pos, &time);
tm[pos] = time;
}
int m;
scanf("%d", &m);
ms(road, inf);
for (int i = 0; i < m; i++)
{
int from, to, need;
scanf("%d,%d,%d", &from, &to, &need);
road[from][to] = need;
road[to][from] = need;
}
int s, t;
scanf("%d,%d", &s, &t);
printf("%d\n", dijkstra(s, t));
return 0;
}
带信号灯的最短路dijkstra问题(阿里巴巴2018校园招聘算法题)的更多相关文章
- 阿里巴巴2017实习生招聘模拟题(部分)---C++后台开发方向
1.一个机器人玩抛硬币的游戏,一直不停的抛一枚不均匀的硬币,硬币有A,B两面,A面的概率为3/4,B面的概率为1/4.问第一次出现连续的两个A年的时候,机器人抛硬币的次数的期望是多少? 9/4 11/ ...
- hdu 2544 最短路 Dijkstra
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2544 题目分析:比较简单的最短路算法应用.题目告知起点与终点的位置,以及各路口之间路径到达所需的时间, ...
- 算法学习笔记(三) 最短路 Dijkstra 和 Floyd 算法
图论中一个经典问题就是求最短路.最为基础和最为经典的算法莫过于 Dijkstra 和 Floyd 算法,一个是贪心算法,一个是动态规划.这也是算法中的两大经典代表.用一个简单图在纸上一步一步演算,也是 ...
- 单源最短路dijkstra算法&&优化史
一下午都在学最短路dijkstra算法,总算是优化到了我能达到的水平的最快水准,然后列举一下我的优化历史,顺便总结总结 最朴素算法: 邻接矩阵存边+贪心||dp思想,几乎纯暴力,luoguTLE+ML ...
- HUD.2544 最短路 (Dijkstra)
HUD.2544 最短路 (Dijkstra) 题意分析 1表示起点,n表示起点(或者颠倒过来也可以) 建立无向图 从n或者1跑dij即可. 代码总览 #include <bits/stdc++ ...
- 训练指南 UVALive - 4080(最短路Dijkstra + 边修改 + 最短路树)
layout: post title: 训练指南 UVALive - 4080(最短路Dijkstra + 边修改 + 最短路树) author: "luowentaoaa" ca ...
- 训练指南 UVA - 10917(最短路Dijkstra + 基础DP)
layout: post title: 训练指南 UVA - 10917(最短路Dijkstra + 基础DP) author: "luowentaoaa" catalog: tr ...
- 训练指南 UVA - 11374(最短路Dijkstra + 记录路径 + 模板)
layout: post title: 训练指南 UVA - 11374(最短路Dijkstra + 记录路径 + 模板) author: "luowentaoaa" catalo ...
- hdu-2544-最短路(dijkstra算法模板)
题目链接 题意很清晰,入门级题目,适合各种模板,可用dijkstra, floyd, Bellman-ford, spfa Dijkstra链接 Floyd链接 Bellman-Ford链接 SPFA ...
随机推荐
- 一步一步配置 Dell OME 监控 Dell 服务器硬件报警
本文包括以下四个部分: 下载 Dell OME 安装 Dell OME 配置 Dell OME 配置 iDRAC 下载 Dell OME 以Dell PowerEdge R730xd 为例 1.登录 ...
- LINQ to SQL 实现 CASE WHEN THEN 语句
Ø 前言 没有什么特别的,只是觉得 LINQ 的功能其实还是蛮强大的,所以简单记录下,算是工作笔记吧,有可能还能帮助到其他同学呢^_^. Ø 下面主要使用了 C# 三元运算符实现实现 SQL 中的 ...
- Javaweb中提到的反射浅析(附源码)
反射:一个jdk5.0的新特性,高级运用.在后期的框架中,这个是一大重点,现在估计我们都不会太多的接触他的.但是为了后面的铺垫,我想还是先了解一下: 先构造一个类,然后我们用反射来获取,调用里面的方法 ...
- Varish 缓存
varish 缓存 2013年06月17日,Varnish Cache 3.0.4 发布,为目前最新版本. varish是以内存作为共享容器的:内存的大小决定了它的缓存容量.相对于主要以硬盘为存储的s ...
- Linux - rm 修复误删文件
fdisk -l # 分区信息lsblk -f # 查看文件类型/etc/fstab # 查看文件格式挂载启动信息 # debugfs针对 ext2 # ext3grep针对 ext3 # extun ...
- QDialog对话框
QDialog对话框,用来实现那些只是暂时存在的用户界面,是独立的窗口,但通常也有父窗口对话框有模态和非模态两种,,非模态对话框的行为和使用方法都类似于普通的窗口,模态对话框则有所不同,当模态对话框显 ...
- gflags命令行参数解析
gflags库是google开源的命令行参数解析工具. 安装 官方没有提供二进制库,但是Debian/Ubuntu平台本身提供了二进制库,可以直接git clone https://github.co ...
- java项目启动时执行指定方法
想到的就是监听步骤如下: 1.配置web.xml <listener> <listener-class>com.listener.InitListener</listen ...
- block循环引用
block里边会有循环引用的风险,它可能对外部一个变量出现强引用,所以需要判断里边是否有循环引用,通过dealloc方法(销毁当前控制器.或销毁要测试的变量),判断是否循环引用.主要在block 里边 ...
- 关于C++中的指针、数组
C++中指针和数组基本等价的原因在于指针算术和C++内部处理数组的方式:将整数变量加一后,其值将增加1:将指针变量加一后,增加的量等于其指向的数据类型的字节数: 指针中存储的是地址,地址在形式上和整数 ...