当青训营遇上码上掘金
前言
本人做题思路借鉴了文章当青训营遇上码上掘金之”寻友之旅“ - 掘金 (juejin.cn),并加入了自己的一部分理解。
题目
主题 3:寻友之旅
小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。
步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1
公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)
请帮助小青通知小码,小青最快到达时间是多久?
输入: 两个整数 N 和 K
输出: 小青到小码家所需的最短时间(以分钟为单位)
思路
这道题属于图论和贪心问题。主要思路是利用广搜算法来搜索从初始节点到目标节点的最短路径。BFS(广度优先搜索)算法,是一种图搜索算法,用于在图中查找最短路径。BFS算法的基本思想是从起始节点开始,沿着图的宽度遍历图中的节点,直到找到目标节点为止。BFS算法可以以最短时间找到最短路径,使用双端队列(deque)存储状态,并且使用一个集合(set)记录访问过的节点,以避免重复访问。 在本题中,小青可以选择步行或公交的方式,步行的速度是每分钟一个节点,公交的速度是每分钟两个节点。为了使小青到达小码的家的最短时间,我们将公交的节点数乘以2,然后进行广搜搜索,寻找最短路径。
总之,BFS算法是一种非常有效的图搜索算法,它可以用来解决很多图搜索问题,而且可以使用双端队列和集合来存储和跟踪已访问的节点,从而提高搜索效率。
实现
from collections import deque
def shortest_time(N, K):
# 创建一个双端队列,存储初始状态
q = deque([(N, 0)])
# 创建一个集合,存储已经访问过的节点
visited = set()
# 当队列不为空时
while q:
# 从队列头取出状态
node, time = q.popleft()
# 如果当前节点为目标节点,则返回时间
if node == K:
return time
# 如果当前节点没有访问过
if node not in visited:
# 将当前节点加入已访问节点集合
visited.add(node)
# 将当前节点步行到下一个节点的状态加入队列
q.append((node - 1, time + 1))
# 将当前节点步行到下一个节点的状态加入队列
q.append((node + 1, time + 1))
# 将当前节点乘坐公交到下一个节点的状态加入队列
q.append((node * 2, time + 1))
# 如果队列为空,则返回-1
return -1
if __name__ == '__main__':
N, K = map(int, "5 17".split())
print(shortest_time(N, K))