抓住那头牛(POJ3278)

抓住那头牛(POJ3278)

题目:
https://cn.vjudge.net/problem/POJ-3278

代码如下:

//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
#define MAX 1000005

int step[MAX];
bool vis[MAX];
queue<int> q;

int bfs(int n,int k)
{
    int head,next;
    q.push(n);
    step[n] = 0;//初始位置花费时间0
    vis[n] = 0;
    while(!q.empty())
    {
        head = q.front();
        q.pop();
        for(int i = 0;i < 3;i++)
        {
            if(i == 0) next = head - 1;
            else if(i == 1) next = head + 1;
            else if(i == 2) next = head * 2;
            if(next < 0 || next >= MAX) continue;
            if(vis[next])
            {
                q.push(next);
                vis[next] = 0;//变成旧点
                step[next] = step[head] + 1;//每走一步花费时间加1
            }
            if(next == k) return step[next];//判断该点是否为牛的位置
        }
    }
}

int main()
{
    int n,k;
    while(~scanf("%d%d",&n,&k))
    {
        memset(step,0,sizeof(step));
        memset(vis,1,sizeof(vis));
        if(n >= k) cout << n - k << endl;
        else cout << bfs(n,k) << endl;
    }
    return 0;
}

广度优先搜索(Breadth First Search)过程:
(1) 把初始节点S0放入Open表中;
(2) 如果Open表为空,则问题无解,失败退出;
(3) 把Open表的第一个节点取出放入 Closed表,并记该节点为n;
(4) 考察节点n是否为目标节点。若是, 则得到问题的解,成功退出;
(5) 若节点n不可扩展,则转第(2)步;
(6) 扩展节点n,将其不在Closed表和 Open表中的子节点(判重)放入Open表的尾部 ,并为每一个子节点设置指向父节点的指针( 或记录节点的层次),然后转第(2)步。
在这里插入图片描述

此题思路:
这道题要分为两种情况,第一种就是牛在农夫左面(也就是n >= k)这个时候农夫最快的走法只能不停的每次往左边移动一个,所以直接输出n - k就是最少时间了。
第二种就是牛在农夫的右侧,首先需要把数轴上每个点都初始化为1(也就是每个点都是新点)然后这个时候就要用bfs去求最短时间了。在bfs函数中首先把农夫的起始位置的坐标放入队列中,随后从队列中取出该值。然后列举从这个点走向下一点所有可能的位置,如果这些位置都是新点并且都在范围中则放入队列中,然后把这些位置的点都变成旧点。并且走到这些点的时间等于上一个点所花时间加一。做完这些步骤后判断该点的位置是否为牛的位置,如果是的就返回走到该点所花的时间,否则再接着搜寻。
简单来说执行bfs是就是先把最初位置放入队列,然后队头出队,并且把从这个点走到下一个点可能的位置都放入队列,然后此时再让队头出队,并把从这个点走到下一个点可能的位置都放入队列,一直执行这个操作。

猜你喜欢

转载自blog.csdn.net/qq_41998938/article/details/84200715