1100 抓住那头牛(bfs)

该博客介绍了如何运用宽度优先搜索(BFS)算法解决一个数学问题:农夫在数轴上追逐一头站在原地不动的牛。农夫有两种移动方式,每次花费1分钟。通过分析移动方式和数据范围,确定搜索范围为[0, 10^5],并利用BFS寻找从农夫初始位置到牛位置的最短时间。代码实现中,使用双端队列进行BFS搜索,并存储每个位置的最短步数,最终找到最短时间并返回结果。
摘要由CSDN通过智能技术生成

1. 问题描述:

农夫知道一头牛的位置,想要抓住它。农夫和牛都位于数轴上,农夫起始位于点 N,牛位于点 K。
农夫有两种移动方式:
从 X 移动到 X−1 或 X+1,每次移动花费一分钟
从 X 移动到 2∗X,每次移动花费一分钟
假设牛没有意识到农夫的行动,站在原地不动。农夫最少要花多少时间才能抓住牛?

输入格式

共一行,包含两个整数N和K。

输出格式

输出一个整数,表示抓到牛所花费的最少时间。

数据范围

0 ≤ N,K ≤ 10 ^ 5

输入样例:

5 17

输出样例:

4
来源:https://www.acwing.com/problem/content/description/1102/

2. 思路分析:

分析题目可以知道我们需要求解从起点N到终点K的最短路径,而且从一个状态到另外一个状态花费的步数为1,所以所有边权都是1,也即可以使用宽搜来解决,这道题目涉及到三个操作,加1,减1和乘2操作,因为宽搜的时间复杂度为O(n),所以需要计算一下可以搜索的范围使得搜索是有意义的,这样可以降低时间复杂度,避免不必要的搜索。首先确定可以移动位置的最小值,可以发现最小值肯定是0,因为如果我们走到了负数的位置而K是大于0的所以只能够通过+1操作再走回来,所以属于来回走了步数反而多了没有什么意义,还不如不走,所以不可能走到负数的位置,那么最小值应该大于等于0,当N在K的右侧那么只能够通过-1的操作走过来,那么最大值小于等于10 ^ 5,当N在K的左侧,可以通过加1和乘2的操作到达K,如果通过乘2的操作使得到达的位置大于了10 ^ 5,那么可以先通过减1再乘2的操作到达K所以最大值也小于等于10 ^ 5,所以我们在操作的时候范围为:[0,10 ^ 5],实际在做的时候可以开大一点的数组,因为需要记录最短距离所以可以使用一个dis数组,dis数组不仅可以记录最短距离而且还可以充当bfs的判重数组,因为第一次搜到的一定是最短的。

3. 代码如下:

import collections


class Solution:
    def bfs(self, n: int, k: int):
        # 数组中最大的位置为N, 最小为0
        N = 10 ** 5 + 10
        q = collections.deque([n])
        dis = [-1] * N
        dis[n] = 0
        while q:
            p = q.popleft()
            # 因为题目一定有解所以当发现到达目标位置的时候直接返回最短距离
            if p == k: return dis[p]
            if p - 1 >= 0 and dis[p - 1] == -1:
                q.append(p - 1)
                dis[p - 1] = dis[p] + 1
            if p + 1 < N and dis[p + 1] == -1:
                q.append(p + 1)
                dis[p + 1] = dis[p] + 1
            if p * 2 < N and dis[p * 2] == -1:
                q.append(p * 2)
                dis[p * 2] = dis[p] + 1

    def process(self):
        n, k = map(int, input().split())
        return self.bfs(n, k)


if __name__ == '__main__':
    print(Solution().process())
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值