【POJ-3287】Catch That Cow

220 阅读1分钟

题目

农夫约翰已被告知逃亡牛的位置,并希望立即抓住她。他开始于一个点N(0≤ N≤100,000)和牛是在点K (0≤ K≤100,000),他们在同一条线上。农夫约翰有两种交通方式:步行和乘车。

  • 行走:约翰可以在一分钟内从任意点X移动到X -1或X + 1 点
  • 乘车:约翰可以在一分钟内从任意点X移动到点2× X

如果母牛不知道它的追赶,根本不动,那么农夫约翰需要多长时间才能找回它?




样例

样例输入
5 17


样例输出
4



解题思路

三叉树:广度优先。从根节点往下遍历,满足条件就加入队列中,同时记录每条路径的长度,即树的高度。等到发现一条可行路径后,该路径的长度或者该树的高度就是走过的步数




AC代码

#include <iostream>
#include <queue>
using namespace std;
int N, K;
int visit[100001];
int height[1000001];
queue<int> q;

int bfs(int N, int K)
{
    //如果开始点在终点右边,则只能通过每次倒退一步的方法到达终点,即需要N-K步
    if (N >= K)
        return N - K;
    //当前位置、下一步的位置
    int now, next;
    //当前位置进队列
    q.push(N);
    height[N] = 0;
    //标记已走过的当前位置
    visit[N] = 1;

    while (!q.empty())
    {
        //取出当前的节点,从这个节点开始搜索
        now = q.front();
        q.pop();
        //在每一个结点都朝三个方向搜索
        for (int i = -1; i <= 1; i++)
        {
            //如果越界或者判重没通过,也不用回溯,因为next初值为0,在每次循环中也是实时更新的;head也会不用管,用为head是从队列中出来的,在for循环里没有被赋值,不会发生改变
            if (i != 0)
                next = now + i;
            else
                next = now * 2;

            //如果越界或者重复,则放弃这条路径
            if (next >= 0 && next <= 100001 && visit[next] == 0)
            {
                q.push(next);
                // cout<<next<<" ";
                //树的高度加1,即路径长度加1
                height[next] = height[now] + 1;
                // cout<<height[next]<<endl;
                //对走过的点进行标记,很重要。
                visit[next] = 1;
            }
            //如果某一步到达终点,则从根节点到这一个节点的树的高度(即长度)就是走过的步数
            if (next == K)
                return height[next];
        }
    }
}
int main()
{
    int N, K;
    cin >> N >> K;
    cout << bfs(N, K) << endl;
}


题源:poj.org/problem?id=…