Catch That Cow(bfs搜索)

Time Limit: 2000ms

Memory Limit: 32768KB

64-bit integer IO format: %I64d      Java class name: Main


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?


Input

Line 1: Two space-separated integers: N and K


Output

Line 1: The least amount of time, in minutes, it takes for Farmer John to catch the fugitive cow.


Sample Input

5 17


Sample Output

4


Hint

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.


AC代码(15ms 1900KB):

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <cstring>
#include <queue>
using namespace std;
int dis[100005];
const int INF=0x3f3f3f3f;
int m,n;
queue<int> q;
int bfs(int sx)
{
    int xx;
    memset(dis,INF,sizeof(dis));
    while (!q.empty()) q.pop();
    q.push(sx);
    dis[sx]=0;
    while(!q.empty()&&xx!=n)
    {
        int x=q.front();
        q.pop();
        xx=x+1;
        if(xx>=0&&xx<=100000&&dis[xx]==INF)
        {
            dis[xx]=dis[x]+1;
            q.push(xx);
  //          cout<<x<<"  "<<dis[x]<<"  "<<xx<<"  "<<dis[xx]<<endl;
        }
        if(xx==n)break;
        xx=x-1;
        if(xx>=0&&xx<=100000&&dis[xx]==INF)
        {
            dis[xx]=dis[x]+1;
            q.push(xx);
  //          cout<<x<<"  "<<dis[x]<<"  "<<xx<<"  "<<dis[xx]<<endl;
        }
        if(xx==n)break;
        xx=x*2;
        if(xx>=0&&xx<=100000&&dis[xx]==INF)
        {
            dis[xx]=dis[x]+1;
            q.push(xx);
    //        cout<<x<<"  "<<dis[x]<<"  "<<xx<<"  "<<dis[xx]<<endl;
        }
        if(xx==n)break;
    }
    cout<<dis[n]<<endl;
}
int main()
{
    while(cin>>m>>n)
    {
        bfs(m);
    }
    return 0;
}

在写的过程中遇到的新知识点:

①在不用结构体只用队列时,queue<>括号中应该填int或double数据的类型

②清空队列的三种方式(使用了方法二,对我来说最容易理解):

方法一

直接用空的队列对象赋值

queue<int> q1;
q1 = queue<int>();

方法二

遍历出队列

while (!q.empty()) q.pop();

方法三

使用swap,这种是最高效的,定义clear,保持STL容器的标准。

void clear(queue<int>& q) {
    queue<int> empty;
    swap(empty, q);
}

经过了多次尝试,以下为出现WA以及改进的过程:

①不使用循环输入的话会WA(不知道为什么),绝对没有endl重复换行。

②使用循环输入时一定要在每一次调用bfs时清空队列,不然同一个队列会混乱:对于xx与x的关系操作时,x并不是理想中的x,所以当xx找到n时也可能由于dis[xx]还是INF导致输出错误的值,不过倒是可以知道0x3f3f3f3f的值啦。

③在队列的while循环中,可以不加xx!=n这个判断条件,因为如果是的话在循环内部已经break过,不会返回到循环条件上。不加的话时间更短(我也很震惊可以快到0ms,只出现了一次,后来复制粘贴的代码也不能AC快到0ms,偶然状况吧)。

条件加多了更麻烦,加了xx!=m之后cout时不能用dis[xx]因为当数字过大时有可能某一种情况遍历到起点就停了,可是还没有到达终点。

④很奇怪,这道题可以重复换行,不会PE,也就是除了在bfs函数里加endl,在主函数中再加一个endl也还是对的。

⑤如果当数字很大时才会出现错误的话真的输出验证会跑很久很久,所以最终还是想了想循环上会出什么错。

猜你喜欢

转载自blog.csdn.net/nlp180720/article/details/81173427