广度搜索--POJ 3278 (经典入门级的广度优先搜索)

poj3278:catch the cow

这里贴上的都是原题,没有附上翻译的版本,大家英语都是杠杠的,想必都是无障碍阅读,实在读不懂,可以百度一下意思。

description:

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 code 1:(这一段代码是参见网上比较优质的AC代码的)

#include<iostream>
#include<cstdio>
#include<queue>

using namespace std;
int n, k, c, ans;
int num[100005];  //定义为全局变量,默认值都是0
int main()
{
    while(cin>>n>>k)
    {
        ans = 0;
        queue<int> q;
        q.push(n);
        num[n] = 0;
        while(q.size())
        {
            c = q.front();
            if(c == k)
            {
                ans = num[c];
                break;
            }
            q.pop();
            if(!num[c-1] && c-1>=0)  // !num[c-1]的意思是,如果c-1没有被执行过,那么就走一走,这就是代码为什么只能执行一次的原因,因为执行过了一次之后,num数组没有被再次置0,下一次循环到这里的时候,就进不去,那么结果就会出错,
            {                                             //这种情况也可以另外设一个falg判断数组,像下面这样       !的意思是取反,0取反为>1的正数
                num[c-1] = num[c] + 1;
                q.push(c-1);
            }
            if(c+1<=100000 && !num[c+1])
            {
                num[c+1] = num[c] + 1;
                q.push(c+1);
            }
            if(c*2<=100000 && !num[2*c])
            {
                num[2*c] = num[c] + 1;
                q.push(2*c);
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

AC code 2:(这一段代码是在自己理解的基础上写的,个人觉得这一段代码理解起来比较容易,适合起步者)

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>   //这个头文件是为了使用memset函数的
using namespace std;
int num[100005];
bool flag[100005];  //这个是跟上面那个代码最大不同的地方,也是代码能够处理多组数据的原因;

int main()
{
    int n,k,c;
    while(cin>>n>>k)
    {
        int ans=0;
        memset(flag,false,sizeof(flag));    //每次开始给flag数组全部预置值为false
        queue<int> q;
        q.push(n);
        num[n]=0;
        while(q.size())
        {
            c=q.front();
            if(c==k)    //如果已经找到了相对应的值,那么就记录下对应的num数组对应的值,然后循环跳出
            {
                ans=num[c];   
                break;
            }
            q.pop();  //这又是容易错的地方,记得每次取出q的front之后,要把它pop出来
            if(c-1>=0&&!flag[c-1])    //每进去一次都要给对应的flag数组的值置为true,表示已经走过了,防止重复走,死循环
            {
                flag[c-1]=true;
                num[c-1]=num[c]+1;
                q.push(c-1);
            }
            if(c+1<=100000&&!flag[c+1])
            {
                flag[c+1]=true;
                num[c+1]=num[c]+1;
                q.push(c+1);
            }
            if(c*2<=100000&&!flag[c*2])
            {
                flag[c*2]=true;
                num[c*2]=num[c]+1;
                q.push(c*2);
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

附上一张以5 17作为样例的图解,希望能帮到大家理解:

原文地址:https://www.cnblogs.com/myxdashuaige/p/8719299.html