4300 两种操作(宽搜)

1. 问题描述:

给定一个正整数 n,我们希望你可以通过一系列的操作,将其变为另一个正整数 m。操作共分两种:
将当前的数乘以 2。
将当前的数减去 1。
要求,在变换过程中,数字始终为正。请你计算,所需要的最少操作次数。

输入格式

一行,两个不同的正整数 n 和 m。

输出格式

一个整数,表示所需的最少操作次数。

数据范围

前 6 个测试点满足 1 ≤ n,m ≤ 10。
所有测试点满足 1 ≤ n,m ≤ 10000。

输入样例1:

4 6

输出样例1:

2

输入样例2:

10 1

输出样例2:

9
来源:https://www.acwing.com/problem/content/description/4303/

2. 思路分析:

分析题目可以知道我们需要求解最少操作次数,属于经典的"最小步数"模型,对于"最小步数"模型一般可以使用宽搜来解决,由题目可知当n > m的时候我们只能够通过减1的操作使得最终变为m的操作次数最小,当n = m的时候不需要任何操作,当n < m的时候尽可能使用乘2操作,2 * n < 2 * m当n > m的时候又会转为减1的操作,所以n的范围不会超过2m,这样在声明距离数组dis的时候声明长度比2m大一点即可,在枚举的时候长度最大不超过2m。

3. 代码如下:

import collections


class Solution:
    def process(self):
        n, m = map(int, input().split())
        N, INF = 20010, 10 ** 10
        # 宽搜一般使用dis数组来记录从起点到某个点的最短距离, 由于第一次到达的距离一定是最短的所以不用标记哪些点是否被访问, 没有被访问过的点的距离一定是正无穷的
        dis = [INF] * N
        dis[n] = 0
        # 双端队列
        q = collections.deque([n])
        while q:
            p = q.popleft()
            if p == m: return dis[p]
            x, y = p * 2, p - 1
            # 在小于N的情况下距离更小那么更新答案
            if x < N and dis[x] > dis[p] + 1:
                dis[x] = dis[p] + 1
                q.append(x)
            if y >= 1 and dis[y] > dis[p] + 1:
                dis[y] = dis[p] + 1
                q.append(y)
        return -1


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值