抓住那头牛 知识点:边权为1可以用bfs求最短路径

60 阅读2分钟

P1588 [USACO07OPEN] Catch That Cow S - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

不论向x-1,x+1移动还是向2x移动都需要花费一分钟,所以所有边的权重都是1:

image.png

如果所有边的权重都是1,那么就可以用bfs求出最短路径。

因为x,y最大都是1e5,但是x是有可能走到大于1e5的位置的,比如当x是50000,y是1e5的时候,那么x第一次走2x就是100002,再回退两步才走到y:

image.png

因此我们要开个M,M要比N大,但不用大太多,M=2N就可以了;

又因为y最大是1d5,因为只有当x>1e5的时候才需要-1操作,当x小于1e5的时候只有+1和2x操作,没有-1操作。

code

#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int>PII;
const int N = 1e5 + 10, M = 2 * N;
int q[M];
int dist[N];

int bfs(int x, int y)
{
    memset(dist, -1, sizeof dist);
    q[0] = x;  //从x开始走
    dist[x] = 0;  //表示为走过了


    int hh = 0, tt = 0;
    while (hh <= tt)
    {
        int t = q[hh++];
        //cout << t << " " << dist[t] << endl;
        if (t == y)return dist[y];  //走到终点了就返回最短路径
        
        if (t + 1 < M && dist[t + 1] == -1)  //如果t+1没有越界并且当前位置没有被遍历过的话
        {
            dist[t + 1] = dist[t] + 1;
            q[++tt] = t + 1;
        }
        if (t - 1 >=0 && dist[t - 1] == -1)  //如果t-1没有越界并且当前位置没有被遍历过的话
        {
            dist[t - 1] = dist[t] + 1;
            q[++tt] = t - 1;
        }
        if (t * 2 < M && dist[t * 2] == -1)  //如果t*2没有越界并且t*2这个位置没有被遍历过的话
        {
            dist[t * 2] = dist[t] +1;
            q[++tt] = t * 2;
        }
    }
    return -1;
}
int main()
{
    int t; cin >> t;
    while (t--)
    {
        int x, y; cin >> x >> y;
        cout << bfs(x, y) << endl;
    }
}