题意:John和它的牛在一天直线上,Joh每次可以向前走一步或者向后走一步或者跳到当前位置的2倍位置上,求John在最少的时间里抓到那牛。
输入:John当前位置和牛所在的位置。
输出:John花的最少时间。
分析:可以将问题转化为从一个点到另一个点的最少步数,这里可以用广搜去做,首先将当前John的位置入队,然后根据John的三种走法依次遍历并且入队,在出队列的时候判断此点是否走过,并且此点的值是否等于牛所在的点的值。如果等于输出到达当前位置所需要的步数。
如果John的位置在牛的位置之前直接输出n-k;
这里可以定义一个step[ ]数组来记录到达每个点时走了多少步。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=100010;
bool vis[maxn]; //标记数组
int step[maxn]; //记录到达每个点所需要的步数
queue<int> q; //队列q;
int bfs(int n,int k)
{
q.push(n);
vis[n]=true;
step[n]=0;
int head,next;
//head=q.front();
while(!q.empty())
{
head=q.front();
q.pop();
// if(head==k)
// return step[head];
for(int i=1;i<=3;i++) //三种走法
{
if(i==1){
next=head+1;
}
else if(i==2)
next=head-1;
else next=head*2;
if(next<0||next>=maxn) continue;
if(!vis[next]){ //没有被访问
q.push(next); //入队
//q.pop(); 在for循环外执行pop操作
step[next]=step[head]+1;
vis[next]=true;
}
if(next==k)
return step[next];
}
}
}
int main()
{
int n,k;
while(~scanf("%d%d",&n,&k))
{
memset(step,0,sizeof(step));
memset(vis,false,sizeof(vis)); //全部设为未访问
while(!q.empty()) q.pop(); //掉用前清空队列
if(n>=k)
printf("%d\n",n-k);
else
printf("%d\n",bfs(n,k));
}
return 0;
}