BFS:抓住那头牛(广度优先搜索入门)

POJ 3278 抓住那头牛

描述

农夫知道一头牛的位置,想要抓住它。农夫和牛都位于数轴上,农夫起始位于点N(0<=N<=100000),牛位于点K(0<=K<=100000)。农夫有两种移动方式:

  1. 从X移动到X-1或X+1,每次移动花费一分钟
  2. 从X移动到2*X,每次移动花费一分钟
    假设牛没有意识到农夫的行动,站在原地不动。农夫最少要花多少时间才能抓住牛?

输入

两个整数,N和K

输出

一个整数,农夫抓到牛所要花费的最小分钟数

样例输入

5 17

样例输出

4

#include
#include
using namespace std;
int N, K;
const int MAXN = 100000;
int visited[MAXN + 10];//判重标记,visited[i]=true表示已经扩展过 
struct Step{
     
	int x;//位置 
	int steps;//到达x所需的步数 
	Step(int p, int s):x(p), steps(s){
     	}//位置和所需步数的赋值函数 
};
queue<Step> q;//队列即Open表 
int main()
{
     
	cin>>N>>K;//输入农夫和牛的位置 
	q.push(Step(N, 0));
	visited[N] = 1;
	while(!q.empty())
	{
     
		Step s = q.front();//取出队列的第一个结点 
		if(s.x == K)
		{
     
			cout<<s.steps<<endl;//找到的第一个解便是最优解 
			return 0;
		}
		else{
     
			if(s.x-1 >= 0 && !visited[s.x-1])//向左扩展结点 
			{
     
				q.push(Step(s.x-1, s.steps+1));//从起点s.x走到终点需要steps步,那么从s.x-1走到终点则需要steps+1步 
				visited[s.x-1] = 1;
			}
			if(s.x+1 <= MAXN && !visited[s.x+1])//向右扩展结点 
			{
     
				q.push(Step(s.x+1, s.steps+1));
				visited[s.x+1] = 1;
			}
			if(s.x*2 <= MAXN && !visited[s.x*2])
			{
     
				q.push(Step(s.x*2, s.steps+1));
				visited[s.x*2] = 1;
			}
		    q.pop();//弹出队头元素 
		}
	}
	return 0;

算法解释

1. 复杂度分析

由于每个结点都只入队出队一次,故此时间复杂度为 o ( n ) o(n) o(n)

2.过程图

BFS:抓住那头牛(广度优先搜索入门)_第1张图片
BFS:抓住那头牛(广度优先搜索入门)_第2张图片
BFS:抓住那头牛(广度优先搜索入门)_第3张图片
BFS:抓住那头牛(广度优先搜索入门)_第4张图片
BFS:抓住那头牛(广度优先搜索入门)_第5张图片
BFS:抓住那头牛(广度优先搜索入门)_第6张图片
BFS:抓住那头牛(广度优先搜索入门)_第7张图片
BFS:抓住那头牛(广度优先搜索入门)_第8张图片
目标结点5出队,问题解决!

广度优先搜索(BFS)算法

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

你可能感兴趣的:(数据结构,队列,bfs)