P1588 [USACO07OPEN] Catch That Cow S 最短路广搜

题目分析

这是一道经典的 一维BFS(广度优先搜索) 题目,要求计算农夫(FJ)从起点 x 到终点 y 的最少步数,每次移动可以选择:

  1. 前进一步(x + 1

  2. 后退一步(x - 1

  3. 直接跳跃到 2 * x 的位置

由于每次移动的步数相同(每一步的代价都是 1),BFS 能够保证首次到达终点时的步数一定是最小的。

代码解析(带详细注释)

#include<bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10;  // 定义坐标的最大范围

struct node {
    int x, step;  // x: 当前坐标,step: 走到当前坐标的步数
};

int vis[N];  // 标记数组,记录某个坐标是否被访问过
int n, k;    // n: 起点,k: 终点(牛的位置)

void bfs(int s) {
    queue<node> q;  // 定义队列,用于BFS
    q.push({s, 0}); // 起点入队,初始步数为0
    vis[s] = 1;     // 标记起点已访问

    while (q.size()) {  // 队列不为空时循环
        int x = q.front().x, st = q.front().step;  // 取出队首元素
        q.pop();  // 弹出队首

        // 遍历三种可能的移动方式
        for (int i = 0; i < 3; i++) {
            int tx;  // 临时变量,存储移动后的新坐标
            if (i == 0) tx = x - 1;  // 后退一步
            if (i == 1) tx = x + 1;  // 前进一步
            if (i == 2) tx = x * 2;  // 跳跃到 2 * x

            // 检查新坐标是否越界或已访问
            if (tx < 0 || tx >= N) continue;  // 越界则跳过
            if (vis[tx] == 0) {  // 如果未访问过
                q.push({tx, st + 1});  // 入队,步数+1
                vis[tx] = 1;           // 标记已访问
            }

            // 如果到达终点,直接输出步数并返回
            if (tx == k) {
                cout << st + 1 << endl;
                return;
            }
        }
    }
}

void solve() {
    cin >> n >> k;  // 输入起点和终点
    memset(vis, 0, sizeof(vis));  // 初始化访问标记数组
    bfs(n);  // 从起点开始BFS
}

int main() {
    int T; cin >> T;  // 输入数据组数
    while

 

posted @ 2025-06-04 19:51  CRt0729  阅读(19)  评论(0)    收藏  举报