【题目大意】
农夫被告知逃亡奶牛所在的位置,并希望能立即抓住奶牛。
他刚开始站在点N(0<=N<=100000)上,并且母牛站在同一条线上的点K(0<=K<=100000)上。农夫先有步行和传送两者交通方式:
1.行走:农夫可以每1分钟从任一点X——>X-1 / X+1
2.传送:农夫可以每1分钟从任一点X——>2X
如果母牛不动,则农夫需要多长时间才能找回它?
思路:
该题非常适合运用BFS算法进行求解。在探讨BFS之前,必须先指明问题中的状态。
因此可以设定状态为二元组(n,t),其中n为农夫当前所在位置的坐标点,t为从起点N走到当前坐标点n所消耗的时间。
由于任意一个状态(n,t)经过1秒后可以转入下一个状态,所以说任意一个状态(n,t)可以扩展为三个状态(n-1,t+1),(n+1,t+1),(2n,t+1)中的合法状态。于是便可从起始状态(N,0)不断扩展到它能够到达的下一个状态,即起点的邻居结点。再按邻居结点访问的先后顺序依次地扩展到它们能够到达的下一个状态,依次类推。当扩展到目标状态(K,t)时,目标状态中的 t 必然为最短耗时。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int MAXN=100001;
struct status{
int n,t;
status(int n,int t)
{
n=n;
t=t;
}
};
bool visit[MAXN];
int BFS(int n,int k){
queue<status> myqueue;
myqueue.push(status(n,0));//压入初始状态
visit[n]=true; //起始点已被访问
while(!myqueue.empty())
{
status current=myqueue.front();
myqueue.pop();
if(current.n==k)//查找成功
return current.t;
for(int i=0;i<3;i++)//转入不同状态
{
status next(current.n,current.t+1);
if(i==0)
next.n+=1;
else if(i==1)
next.n-=1;
else
next.n*=2;
if(next.n<0||next.n>=MAXN||visit[next.n])
continue;//新状态不合法
myqueue.push(next);//压入新的状态
visit[next.n]=true;//该点已被访问
}
}
}
int main()
{
int n,k;
cin>>n>>k;
memset(visit,false,sizeof(visit));//初始化;
cout<<BFS(n,k)<<endl;
return 0;
}