POJ 3278 抓住那头牛
描述
农夫知道一头牛的位置,想要抓住它。农夫和牛都位于数轴上,农夫起始位于点N(0<=N<=100000),牛位于点K(0<=K<=100000)。农夫有两种移动方式:
- 从X移动到X-1或X+1,每次移动花费一分钟
- 从X移动到2*X,每次移动花费一分钟
假设牛没有意识到农夫的行动,站在原地不动。农夫最少要花多少时间才能抓住牛?
输入
两个整数,N和K
输出
一个整数,农夫抓到牛所要花费的最小分钟数
样例输入
5 17
样例输出
4
#include<iostream>
#include<queue>
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.过程图
目标结点5出队,问题解决!
广度优先搜索(BFS)算法
(1) 把初始节点S0放入Open表中;
(2) 如果Open表为空,则问题无解,失败退出;
(3)把Open表的第一个节点取出放入Closed表,并记该节点为n;
(4) 考察节点n是否为目标节点。
若是,则得到问题的解,成功退出;
(5) 若节点n不可扩展,则转第(2)步;
(6) 扩展节点n,将其不在Closed表和Open表中的子节点(判重)放入Open表的尾部,并为每一个子节点设置指向父节点的指针(或记录节点的层次),然后转第(2)步。