题目描述

现在城市有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校园招聘算法题)的更多相关文章

  1. 阿里巴巴2017实习生招聘模拟题(部分)---C++后台开发方向

    1.一个机器人玩抛硬币的游戏,一直不停的抛一枚不均匀的硬币,硬币有A,B两面,A面的概率为3/4,B面的概率为1/4.问第一次出现连续的两个A年的时候,机器人抛硬币的次数的期望是多少? 9/4 11/ ...

  2. hdu 2544 最短路 Dijkstra

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2544 题目分析:比较简单的最短路算法应用.题目告知起点与终点的位置,以及各路口之间路径到达所需的时间, ...

  3. 算法学习笔记(三) 最短路 Dijkstra 和 Floyd 算法

    图论中一个经典问题就是求最短路.最为基础和最为经典的算法莫过于 Dijkstra 和 Floyd 算法,一个是贪心算法,一个是动态规划.这也是算法中的两大经典代表.用一个简单图在纸上一步一步演算,也是 ...

  4. 单源最短路dijkstra算法&&优化史

    一下午都在学最短路dijkstra算法,总算是优化到了我能达到的水平的最快水准,然后列举一下我的优化历史,顺便总结总结 最朴素算法: 邻接矩阵存边+贪心||dp思想,几乎纯暴力,luoguTLE+ML ...

  5. HUD.2544 最短路 (Dijkstra)

    HUD.2544 最短路 (Dijkstra) 题意分析 1表示起点,n表示起点(或者颠倒过来也可以) 建立无向图 从n或者1跑dij即可. 代码总览 #include <bits/stdc++ ...

  6. 训练指南 UVALive - 4080(最短路Dijkstra + 边修改 + 最短路树)

    layout: post title: 训练指南 UVALive - 4080(最短路Dijkstra + 边修改 + 最短路树) author: "luowentaoaa" ca ...

  7. 训练指南 UVA - 10917(最短路Dijkstra + 基础DP)

    layout: post title: 训练指南 UVA - 10917(最短路Dijkstra + 基础DP) author: "luowentaoaa" catalog: tr ...

  8. 训练指南 UVA - 11374(最短路Dijkstra + 记录路径 + 模板)

    layout: post title: 训练指南 UVA - 11374(最短路Dijkstra + 记录路径 + 模板) author: "luowentaoaa" catalo ...

  9. hdu-2544-最短路(dijkstra算法模板)

    题目链接 题意很清晰,入门级题目,适合各种模板,可用dijkstra, floyd, Bellman-ford, spfa Dijkstra链接 Floyd链接 Bellman-Ford链接 SPFA ...

随机推荐

  1. Vue.js入门系列教程(二)

    过滤器:filter 全局过滤器 <!DOCTYPE html> <html lang="en"> <head> <meta charse ...

  2. C# PointToScreen

    子窗体定位时,如果主窗口不在左上角,需要根据主窗口的坐标,相减才行. Point p1 = Label.PointToScreen(new Point(0, 0)); p1.X -= this.X; ...

  3. 通过read()读文件

    一.在POSIX中的定义 #include <unistd.h> ssize_t read(int fd, void *buf, size_t len); 二.调用read()的可能结果 ...

  4. u-boot移植(四)---修改前工作:代码流程分析3---代码重定位

    一.重定位 1.以前版本的重定位 2.新版本 我们的程序不只涉及一个变量和函数,我们若想访问程序里面的地址,则必须使用SDRAM处的新地址,即我们的程序里面的变量和函数必须修改地址.我们要修改地址,则 ...

  5. 20155332 2016-2017-2 《Java程序设计》第8周学习总结

    20155332 2016-2017-2 <Java程序设计>第8周学习总结 教材学习内容总结 创建Logger对象 static Logger getLogger(String name ...

  6. Java SE之Java中堆内存和栈内存[转/摘]

    [转/摘]1-3Java中堆内存和栈内存 注解:内存(Memory)即 内存储器,主存,其作用是用于暂时存放CPU中的运算数据,以及与硬盘等外部存储器(辅存)交换的数据. Java中把内存分为两种:栈 ...

  7. 之手算KD-tree

    转自:https://zhuanlan.zhihu.com/p/27453420 本文来源于Machine Learning: Clustering & Retrieval | Courser ...

  8. Docker三要素

    一.镜像(Image) Docker镜像(Image)就是一个只读的模板,镜像可以用来创建Docker容器,一个镜像可以创建很多容器. Docker 面向对象 镜像 类(class) 容器 实例对象 ...

  9. Windows Server2008各版本区别

    Windows Server 2008 是专为强化下一代网络.应用程序和 Web 服务的功能而设计,是有史以来最先进的 Windows Server 操作系统.拥有 Windows Server 20 ...

  10. 八大最安全的Linux发行版,具备匿名功能,做服务器的首选,web,企业服务器等

    10 best Linux distros for privacy fiends and security buffs in 2017 Introduction The awesome operati ...