Catch That Cow 抓住那头牛

POJ - 3278

题目来源

POJ - 3278

题目内容

Farmer John has been informed of the location of a fugitive cow and wants to catch her immediately. He starts at a point N (0 ≤ N ≤ 100,000) on a number line and the cow is at a point K (0 ≤ K ≤ 100,000) on the same number line. Farmer John has two modes of transportation: walking and teleporting.

* Walking: FJ can move from any point X to the points X - 1 or X + 1 in a single minute
* Teleporting: FJ can move from any point X to the point 2 × X in a single minute.

If the cow, unaware of its pursuit, does not move at all, how long does it take for Farmer John to retrieve it?

知识点

搜索:广(宽)度搜索BFS

题目思路

The fastest way for Farmer John to reach the fugitive cow is to move along the following path: 5-10-9-18-17, which takes 4 minutes.
农夫约翰最快到达逃跑的奶牛的方法是沿着以下路径移动:5-10-9-18-17,这需要4分钟。

使用广度优先搜索(BFS)来解决这个问题。
假设起点是N,终点是K,我们可以从起点开始,每次移动都有三种可能性:

  1. 步行到X-1点;
  2. 步行到X+1点;
  3. 传送到2×X点。

我们可以将每个点看作一个节点,根据这三种移动方式构建一个图。然后使用BFS遍历图,直到找到终点K为止。在遍历的过程中,我们可以记录每个点所经过的步数,以便后续计算总共需要的时间。

具体步骤如下:

  1. 定义一个队列来存储待遍历的节点,初始化时将起点N加入队列;
  2. 定义一个数组dist,用来记录每个点的步数,初始化时将所有点的步数设置为一个较大的值,表示未访问过;
  3. 设置起点N的步数为0,表示已经访问过;
  4. 使用while循环来遍历队列中的节点,直到队列为空为止;
  5. 在循环内部,取出队列的第一个节点,判断是否为终点K,如果是,则返回该节点的步数,表示找到了终点;
  6. 否则,对当前节点进行三种移动操作,判断移动后的点是否已经访问过(即dist数组中的值是否为一个较大的值),如果没有访问过,则将该点加入队列,并将其步数设置为当前节点的步数加1;
  7. 重复步骤4-6,直到找到终点K为止。

最后,返回终点K在dist数组中的步数,即为所需的时间。我们可以使用广度优先搜索(BFS)来解决这个问题。假设起点是N,终点是K,我们可以从起点开始,每次移动都有三种可能性:

  1. 步行到X-1点;
  2. 步行到X+1点;
  3. 传送到2×X点。

我们可以将每个点看作一个节点,根据这三种移动方式构建一个图。然后使用BFS遍历图,直到找到终点K为止。在遍历的过程中,我们可以记录每个点所经过的步数,以便后续计算总共需要的时间。

具体步骤如下:

  1. 定义一个队列来存储待遍历的节点,初始化时将起点N加入队列;
  2. 定义一个数组dist,用来记录每个点的步数,初始化时将所有点的步数设置为一个较大的值,表示未访问过;
  3. 设置起点N的步数为0,表示已经访问过;
  4. 使用while循环来遍历队列中的节点,直到队列为空为止;
  5. 在循环内部,取出队列的第一个节点,判断是否为终点K,如果是,则返回该节点的步数,表示找到了终点;
  6. 否则,对当前节点进行三种移动操作,判断移动后的点是否已经访问过(即dist数组中的值是否为一个较大的值),如果没有访问过,则将该点加入队列,并将其步数设置为当前节点的步数加1;
  7. 重复步骤4-6,直到找到终点K为止。

最后,返回终点K在dist数组中的步数,即为所需的时间。

AC代码

#include "iostream" // 引入输入输出流库
#include "queue" // 引入队列库
using namespace std; // 使用标准命名空间

int a, b; // 定义两个全局变量a和b
const int MAXN = 1e5 + 5; // 定义一个常量,表示数组的最大长度
int f[MAXN]; // 定义一个数组,用于存储到达每个数字的最小步数
queue<int> q; // 定义一个队列,用于BFS的遍历

// BFS函数,用于找到从a到b的最小步数
void bfs() {
    q.push(a); // 将起始数字a放入队列
    while (q.size()) { // 当队列不为空时进行循环
        int t =  q.front(); // 获取队列前端的数字
        q.pop(); // 将队列前端的数字弹出
        if (t == b ) { // 如果这个数字是目标数字b
            printf("%d", f[t]); // 输出到达b的最小步数
            return ; // 函数结束
        }
        // 以下是尝试三种不同的操作,并更新对应的步数
        if (t - 1 >= 0 && !f[t - 1]) f[t - 1 ] = f[t] + 1, q.push(t - 1); // 数字减1
        if (t + 1 <= b && !f[t + 1]) f[t + 1 ] = f[t] + 1, q.push(t + 1); // 数字加1
        if (t << 1 <= b && !f[t << 1]) f[t << 1 ] = f[t] + 1, q.push(t << 1); // 数字乘2

    }
    return ; // 函数结束
}

int main () {
    scanf("%d%d",&a,&b); // 输入起始数字和目标数字
    bfs(); // 调用BFS函数

    return 0; // 程序结束
}

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值