[bfs] 红红去小寨(bfs最短路+思维)

本文介绍了一道编程题,题目中红红需要从当前位置通过三种方式(向前、向后、空间移动)到达公交车站,并希望以最短时间到达。由于无法逆推最优路径,因此采用了广度优先搜索(BFS)来寻找最小步数。代码中通过数组模拟队列,同时用dist数组记录每个位置的最短步数。对于不同输入样例,给出了相应的最短时间解决方案。
摘要由CSDN通过智能技术生成

题目描述

红红今天中午想去市中心吃饭,他决定坐公交车去。但是去公交车的时候红红决定练习一下空间魔法,穿梭时空

现在红红到公交车的路是一条直线,然后他可以通过三种方式移动:

  1. 向前走一个位置

  2. 向后走一个位置

  3. 空间移动,将自己的位置从 x 移动到 2 * x

三种移动方式都需要 10 s

但是红红希望能尽量减少体力的消耗, 所以他希望能以最短的时间到达公交车站

输入

有多组测试样例

每组测试样例包括一个 nk ( 0 < n, k<= 100000)

n 表示红红目前的位置

k 表示公交车站的位置

输出

输出公交车站所需要的最小用时,输出 x:x (表示几分几秒)

样例输入

5 17
7 4
5 10000

样例输出

0:40
0:30
2:10

提示

N 可能大于 K


分析与代码

以前遇到的题目大多都是 *2,+1 / -1+1-1 两种操作不会同时出现,采用逆推的方式就能解决该问题。但是本题缺无法逆推,因为无法确定的知道奇数情况下是通过 +1 还是 -1 变成偶数情况的。

本题操作步数越小越好,且每步操作可看作权值一样,都是只能选择三种方案的其中一种,故可以进行 bfs,得到转换操作的最小步数即可。

代码采用数组模拟队列,dist 数组有三种状态,初始化为 -1 表示该数字不能到达,起点值为 0,每一步的转换更新 dist 数组即可。即优化掉了判重数组,dist 同时完成了判重+记录转化步数的功能,也是常见技巧。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
 
using namespace std;
 
const int N = 100005;
 
int q[N];
int n, k;
int res;
int dist[N];
 
void bfs(int x) {
    memset(dist, -1, sizeof dist);
     
    int hh = 0, tt = 0;
     
    dist[x] = 0;
     
    q[tt ++ ] = x;
     
    while (hh <= tt) {
        int t = q[hh ++ ];
         
         // 三种操作依次进行,操作不论先后,先搜到的数一定是最小的转化步骤
        int u;
        for (int i = 0; i < 3; i ++ ) {		
            if (i == 0) u = t + 1;
            else if (i == 1) u = t - 1;
            else if (i == 2) u = t * 2;
         
            if (u < 0 || u > N) continue;
            if (dist[u] == -1) {
                dist[u] = dist[t] + 1;
                q[tt ++ ] = u;
            }
            if (u == k) {
                res = dist[u];
                return ;
            }
        }
    }
}
 
int main(){
    while (cin >> n >> k) {
        if (n >= k) {
            int t = (n - k) * 10;
            printf("%d:%d\n", t / 60, t % 60);
        } else {
            bfs(n);
            int t = res * 10;
            printf("%d:%d\n", t / 60, t % 60);
        }
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ypuyu

如果帮助到你,可以请作者喝水~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值