【蓝桥刷题】备战国赛——交通信号

news2024/11/16 5:42:17

蓝桥杯2022国赛真题——交通信号



🚀 每日一题,冲刺国赛 🚀

在这里插入图片描述



题目导航:

交通信号

在这里插入图片描述

🎇思路: d i j k s t r a dijkstra dijkstra

🔱思路分析:

要求从一点到另一点的最短距离,即为单源最短路径问题,用 d i j k s t r a dijkstra dijkstra算法

step

🚀1.构图:

本题描述为有向图,但其实是一个的无向图,其权值相同,只是能通过时所对应的灯的颜色不同,正向走对应绿灯时能通过,反向走对应红灯时能通过

在这里插入图片描述


而难点就在于如何构图,每条边之间不仅有权值(边长 = = == ==黄灯时间),还可能存在等待相应灯的时间,也就是说,每到一个新的结点时,在继续前往下一个结点之前,要先看红绿灯,因此,对于此类边上信息复杂的图,我们 用类表示一条边

c l a s s   E d g e : class\ Edge: class Edge:

  • self.to_red:到达红灯的时间
  • self.circle:一个周期:绿 → → → → → →
  • forward(t):表示当前结点到另一结点时正向走的,即只有绿灯时能走, t t t 表示当前时间, r e t u r n return return 到绿灯时需要等待的时间
  • back(t):表示当前结点到另一结点是反向走的,即只有红灯时能走, t t t 表示当前时间, r e t u r n return return 到红灯时需要等待的时间

class Edge:
    def __init__(self,green,red,yellow):
        self.g,self.r,self.d=green,red,yellow # 存放该边上的绿灯、红灯时间和距离
        self.to_red=self.g+self.d  # 到达红灯的时间
        # 一个循环的时间: 绿 -> 黄 -> 红 -> 黄
        self.circle=self.g+self.r+self.d+self.d # 一个周期的时间

    def forward(self,t): # 计算正向时的时间
        t%=self.circle
        return self.d+ (0 if t<self.g else self.circle-t) # 通过时间+等待时间

    def back(self,t): # 计算反向时的时间
        t=(t-self.to_red)%self.circle # 以红灯为周期起点
        return self.d+ (0 if t<self.r else self.circle-t)

再用邻接表存放这些结点和边,对于给出的点 i , j i,j i,j 来说,正向为: i → j i→j ij,反向为: j → i j→i ji

而这里涉及到了 p y t h o n python python的两个语法:

1. ∗ * 打包与解引用:

*a=tuple(map(int,input().split())):表示打包,将输入的元素打包为元组(或列表)类型,带 ∗ * 的赋值目标必须位于列表或元组中

e=Edge(*a):表示对打包的元组 a a a 进行解引用再作为参数到类中


2. 元组内存放类内方法:

P y t h o n Python Python中,方法实际上是定义在类中的函数,可以像其他函数一样存储在元组中,但是需要注意,通过元组调用方法时,需要使用对应的对象或类来调用。例如:

class MyClass:
    def my_method(self,t):
        print("Hello World"+t)

my_tuple = (MyClass().my_method,1)
my_tuple[0]('!') # 输出:Hello World!

因此,我们可以在结点 i , j i,j i,j 对应的元组中存放不同的方法,在调用时,直接按照对应的方法得到等待时间即可,对于正向 i → j i→j ij,到绿灯的时间即为等待时间,存放 f o r w a r d forward forward 方法;反向为 j → i j→i ji,到红灯的时间即为等待时间,存放 b a c k back back 方法:


n,m,start,end=map(int,input().split())
g=[[] for _ in range(n+1)] # 存图
for _ in range(m):
    i,j,*a=tuple(map(int,input().split())) # 这里*a是将剩余的传入的参数打包为元组(g,r,d)
    e=Edge(*a)  # 这里的*a是将元组a=(g,r,d)解包为g,r,d初始化一个类
    g[i].append((j,e.forward)) # 对于i来说,到结点j为正向,并传递计算时间类内方法
    g[j].append((i,e.back))    # 对于j来说,到结点i为反向


🚀2. D i j k s t r a Dijkstra Dijkstra 算法

D i j k s t r a Dijkstra Dijkstra 算法:即每一轮不断选取当前的路径最短且未被确定为最短路径的点,该点的值即为到达该点的最短路径,做上标记,并以该点去更新与之相邻且未确定最短路径的结点的值,取 m i n min min,直到所有结点都已经得到了最短路径

🎁图解算法:

  1. 先构建一张图,初始化到所有点的最短路径为 ∞ ∞

    在这里插入图片描述


  1. 假设要求点 A → F A→F AF 的最短路径,我们则以点 A A A 为源点,则到点 A A A 的最短距离为 0 0 0

    在这里插入图片描述


  1. 此时不难发现,所有点中,路径最小的点即为 A A A,则表示 A A A 已经找到了最短路径,做上标记,并更新与 A A A 相邻点 B , C B,C B,C 的最短距离

    在这里插入图片描述


  1. 更新之后,此时的最短路径对应的点为点 C C C,表示点 C C C 已经找到了最短路径,做上标记之后,更新与 C C C 相邻的未做标记的点 B , D , E B,D,E B,D,E 的最短路径

    在这里插入图片描述


  1. 重复操作,直到遍历完整张图,得到源点到 F F F 点的最短路径

    在这里插入图片描述

由于 d i j k s t r a dijkstra dijkstra 算法需要不断得到当前的最小路径对应的结点,因此我们用小根堆对当前结点进行储存

💫 p y t h o n python python中的优先队列即为小根堆,即内部的存储结构为二叉树,树的根结点保证为最小权值点,其数组的存储方式为层序存储:

在这里插入图片描述

🎇优先队列 P r i o r i t y Q u e u e PriorityQueue PriorityQueue

  • 导包: f r o m   q u e u e   i m p o r t   P r i o r i t y Q u e u e from\ queue\ import\ PriorityQueue from queue import PriorityQueue
  • 入队: q . p u t ( ) q.put() q.put()
  • 出队: q . g e t ( ) q.get() q.get()
  • 队列大小: q . q s i z e ( ) q.qsize() q.qsize()

代码实现:

from queue import PriorityQueue

def dijkstra(start):
    """
    源点:start
    到源点某结点的最短时间数组:d
    优先队列:v
    结点的被标记情况:vis
    """
    d=[float('inf') for _ in range(n+1)] # d[i]表示源点start到点i的最短时间
    d[start]=0
    vis=[True for _ in range(n+1)] # True:已找到最短路径;False:未找到最短路径
    v=PriorityQueue()  # 实例化优先队列
    v.put((0,start))   # 记录当前到结点node的最短距离 (d,node)
    while v:
        m=v.get()[1]   # 利用优先队列得到当前距里源点最近的点
        if m==end:
            break
        if vis[m]:     # 如果点m还未找到最短路径
            vis[m]=False
            for m_node,get_time in g[m]:  # 访问与结点m相邻的点
                if vis[m_node]:   # 还是先判断与m相邻的点是否被标记过,避免重复判断
                    time=d[m]+get_time(d[m])  # 得到这条路径到m_node的时间
                    if time<d[m_node]:
                        d[m_node]=time
                        v.put((d[m_node],m_node))
        else:
            continue   # 表示当前结点是之前已经找到最短距离的点

    return d[end]

d i j k s t r a dijkstra dijkstra 算法实现:

from queue import PriorityQueue

class Edge:
    def __init__(self,green,red,yellow):
        self.g,self.r,self.d=green,red,yellow # 存放该边上的绿灯、红灯时间和距离
        self.to_red=self.g+self.d  # 到达红灯的时间
        # 一个循环的时间: 绿 -> 黄 -> 红 -> 黄
        self.circle=self.g+self.r+self.d+self.d # 一个周期的时间

    def forward(self,t): # 计算正向时的时间
        t%=self.circle
        return self.d+ (0 if t<self.g else self.circle-t) # 通过时间+等待时间

    def back(self,t): # 计算反向时的时间
        t=(t-self.to_red)%self.circle # 以红灯为周期起点
        return self.d+ (0 if t<self.r else self.circle-t)


def dijkstra(start):
    """
    源点:start
    到源点某结点的最短时间数组:d
    优先队列:v
    结点的被标记情况:vis
    """
    global d,vis
    v=PriorityQueue()  # 实例化优先队列
    v.put((0,start))   # 记录当前到结点node的最短距离 (d,node)
    while v:
        m=v.get()[1]   # 利用优先队列得到当前距里源点最近的点
        if m==end:
            break
        if vis[m]:     # 如果点m还未找到最短路径
            vis[m]=False
            for m_node,get_time in g[m]:  # 访问与结点m相邻的点
                if vis[m_node]:   # 还是先判断与m相邻的点是否被标记过,避免重复判断
                    time=d[m]+get_time(d[m])  # 得到这条路径到m_node的时间
                    if time<d[m_node]:
                        d[m_node]=time
                        v.put((d[m_node],m_node))
        else:
            continue   # 表示当前结点是之前已经找到最短距离的点

    return d[end]


n,m,start,end=map(int,input().split())
g=[[] for _ in range(n+1)] # 存图
for _ in range(m):
    i,j,*a=tuple(map(int,input().split())) # 这里*a是将剩余的传入的参数打包为元组(g,r,d)
    e=Edge(*a)  # 这里的*a是将元组a=(g,r,d)解包为g,r,d初始化一个类
    g[i].append((j,e.forward)) # 对于i来说,到结点j为正向,并传递计算时间类内方法
    g[j].append((i,e.back))    # 对于j来说,到结点i为反向

d=[float('inf') for _ in range(n+1)] # d[i]表示源点start到点i的最短时间
d[start]=0
vis=[True for _ in range(n+1)] # True:已找到最短路径;False:未找到最短路径

res=dijkstra(start)
if res<float('inf'):
    print(res)
else:
    print(-1)

输出结果:

在这里插入图片描述



🎇此题为2022年 p y t h o n python python国赛研究生组的一道图论题,今天的考点是~🎇

d i j k s t r a dijkstra dijkstra 算法!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

软件测试的生命周期、Bug

一、软件测试的生命周期 1、软件的生命周期&#xff1a; 需求分析&#xff1a;分析需求是否正确、完整。 设计&#xff1a;项目的上线时间、开始开发时间、测试时间、人员... 计划&#xff1a;设计技术文档、进行UI设计... 编码&#xff1a;写代码&#xff08;实现用户需求&am…

Tomcat启动闪退的详细解决方法(捕获的野生的java1.8.0_321和野生的Tomcat8实验)

1.实验说明 本实验将采用捕获的野生的java1.8.0_321和野生的Tomcat8进行实验。而且不需要安装服务。 2.配置声明&#xff1a; java -version javac -version CATALINA_HOME 说明&#xff1a;CATALINA_HOME配置到放置到tomcat的目录 Path 说明&#xff1a;Path路径配置到tomca…

如和使用matlab实现香农编码和解码

文章目录 前言效果截图如下代码解析完整代码完结 撒花 前言 在网上看了好多 , 都是对香农进行编码的案例 , 却没有 进行解码的操作 , 今天就来补齐这个欠缺 效果截图如下 代码解析 text 你好; % 待编码的文本定义一个字符串类型的变量text&#xff0c;其值为’你好’。 [en…

2023水博会新热门:北斗时空智能 助力水利数字孪生

当“北斗”遇上“智慧水利”将会碰撞出怎样的新意&#xff1f; 6月7日&#xff0c;2023中国水博会暨第十八届中国&#xff08;国际&#xff09;水务高峰论坛正式召开。会上&#xff0c;由千寻位置提出的“北斗时空智能助力水利数字孪生”理念及相应解决方案&#xff0c;受到了与…

肠道菌群、性激素与疾病:探索它们的交互作用

谷禾健康 我们的身体中有很多不同的器官&#xff0c;组织&#xff0c;腺体等会产生许多信号分子来精确控制和影响身体的反应和活动&#xff0c;这些信号分子包括激素、神经递质、生长因子、细胞因子等。它们可以促进或抑制细胞的生长和分化&#xff0c;调节细胞间的相互作用和通…

搭建lanproxy客户端与服务端实现内网穿透

一、首先要配置java环境 1.可以使用这个&#xff0c;或者官网下载&#xff0c;或者其他版本皆可。https://download.csdn.net/download/qq_44821149/87878658 2.采用jdk-8u144-linux-x64.zip压缩包。java version 为1.8.0_144。 3.具体操作为&#xff1a; mkdir /usr/java u…

使用 Iptables 命令详细图文教程

目录 一、防火墙管理工具 二、Iptables 2.1 策略与规则链 2.2 基本的命令参数 2.2.1. 在 iptables 命令后添加 -L 参数查看已有的防火墙规则链。 2.2.2 在 iptables 命令后添加 -F 参数清空已有的防火墙规则链。 2.2.3 把 INPUT 规则链的默认策略设置为拒绝。 2.2.4…

【Web服务应用】部署LVS-DR集群

LVS-DR集群 一、LVS-DR工作原理二 、DR数据包流向分析2.1DR模式中名词解释2.2数据包流向 三、ARP问题3.1问题一&#xff1a;IP 地址冲突3.2 问题二&#xff1a;第二次再有访问请求 四、LVS-DR实战 一、LVS-DR工作原理 LVS-DR&#xff08;Linux Virtual Server Director Server&…

Pandas的groupby用法说明

Pandas的groupby用法说明 1、功能说明 按官方文档说明groupby功能&#xff0c;可以参考与SQL中的分组操作进行理解。 By “group by” we are referring to a process involving one or more of the following steps: Splitting the data into groups based on some criteri…

VMware® vSphere虚拟化平台限制虚拟机网卡速率一例

本文介绍VMware vSphere对虚拟服务器进行网卡限速的案例 一、案例背景 目前有一套生产环境的虚拟化平台基于VMware vSphere构建。宿主机外连网卡均为主、备各10Gb&#xff0c;核心交换机出口至外部网络带宽也是10Gb。某业务系统使用nginx搭建了两台固件升级服务器对外提供下载…

Spark RDD的创建

文章目录 一、RDD为何物&#xff08;一&#xff09;RDD概念&#xff08;二&#xff09;RDD示例&#xff08;三&#xff09;RDD主要特征 二、做好准备工作&#xff08;一&#xff09;准备文件1、准备本地系统文件2、启动HDFS服务3、上传文件到HDFS &#xff08;二&#xff09;启…

免费升级到 iOS 17 Developer Beta:官方Apple Store升级方案与爱思助手方法比较

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

【unity】几种常用的拖拽方法(内置方法 + 接口 + Event Trigger组件)

前言 在Unity中实现拖拽的方法有多种&#xff0c;以下是几种常见的方法和它们的优缺点 1. 鼠标按键的点击事件 Input.GetMouseButtonDown和Input.GetMouseButtonUp 方法可以监测用户鼠标按键的点击事件&#xff0c;通过检测鼠标按钮的状态来实现拖拽效果。用户通过鼠标进行拖…

DolphinScheduler3.1.4 集群部署

文章目录 DolphinScheduler3.1.4 集群部署一、解压 dolphinScheduler3.1.4 安装包二、复制 mysql8.0.16 的驱动三、创建mysql数据库用户和权限四、配置 dolphinscheduler_env.sh 文件五、初始化元数据六、配置 install_env.sh 文件七、安装 dolphinScheduler DolphinScheduler3…

2核4G服务器阿里云4M和腾讯云5M性能价格对比

阿里云轻量应用服务器2核4G4M带宽297.98元12个月&#xff0c;腾讯云轻量2核4G5M服务器168元一年&#xff0c;628元3年&#xff0c;2核4G轻量应用服务器阿里云和腾讯云怎么选择&#xff1f;哪个性能比较好&#xff1f;阿腾云分享轻量应用服务器2核4G配置阿里云和腾讯云CPU、带宽…

插件分享 | Headshot ⼀击即中,对指定URL进行漏洞批量扫描

前言&#xff1a;在⼀次真实的攻防场景中&#xff0c;我们发现了⼀个存在 Struts2 漏洞的地址&#xff0c;这个地址在我们通过 Fuzz 获得的⼆级⽬录下&#xff0c;这使得 Goby 的爬⾍没有办法爬取到这⼀个⻚⾯&#xff0c;但是我们通过其它 Struts2 专扫⼯具检测发现这个地址确…

入行软件测试一年了,薪资涨到18K,太强了...

梦的开始 收到了领导的通知&#xff0c;说我这一年来表现的很优秀&#xff0c;准备给我加工资。今天收到工资到账短信&#xff0c;扣掉税&#xff0c;比以往多了3k多&#xff0c;再加上年终奖这些&#xff0c;月薪也到了18k&#xff0c;真的太开心了。 仔细想想这一年来&#…

2023软件测试面试热点问题,你真的了解吗?

收集了2023年所有朋友软件测试的面试题后&#xff0c;我特意整理出了7个高频出现的面试题&#xff0c;一起来看看。 高频问题1&#xff1a;请自我介绍下&#xff1f; 高频问题2&#xff1a;请介绍下最近做过的项目&#xff1f; 高频问题3&#xff1a;请介绍下你印象深刻的bug&a…

MSE播放fragmented mp4 问题记录

一、在使用MSE 播放视频的时候发现firfox能播放,chrome 不能播放 原因&#xff1a;两边要求的fragmented mp4的格式要求不一样 , 参照Transcoding assets for Media Source Extensions - Web APIs | MDN 用ffmpeg 转成 对应的格式 firefox ffmpeg -i mp4-264.mp4 -movflags f…

DatenLord开源产品技术分享 | Xline源码解读 No.2

传统单数据中心解决方案无法满足跨数据中心的场景对性能和一致性的需求。DatenLord推出开源分布式KV存储Xline&#xff0c;针对多数据中心场景&#xff0c;可以实现数据的高性能跨云、跨数据中心共享访问&#xff0c;并且保证数据的一致性。 本期源码解读将聚焦Xline的Lease机…