BFS入门例题
Catch That Cow
题目描述:
Farmer John has been informed of the location of a fugitive cow and wants to catch her immediately. He starts at a point N (0 ≤ N ≤ 100,000) on a number line and the cow is at a point K (0 ≤ K ≤ 100,000) on the same number line. Farmer John has two modes of transportation: walking and teleporting.
- Walking: FJ can move from any point X to the points X - 1 or X + 1 in a single minute
- Teleporting: FJ can move from any point X to the point 2 × X in a single minute.
If the cow, unaware of its pursuit, does not move at all, how long does it take for Farmer John to retrieve it?
Input:
Line 1: Two space-separated integers: N and K
Output:
Line 1: The least amount of time, in minutes, it takes for Farmer John to catch the fugitive cow.
Sample Input:
5 17
Sample Output:
4
Hint:
The fastest way for Farmer John to reach the fugitive cow is to move along the following path: 5-10-9-18-17, which takes 4 minutes.
思路
这道题中农夫和母牛在一条线上,让我们寻找农夫找到母牛的最短时间,即找到母牛的最短路径,因为每一种走法所耗费的时间都是一样的
我们有三种走法,可以后退一步,可以前进一步,可以直接到二倍于当前位置的点
按照这三种走法,暴力搜索即可,每走一步,只要不超过限制范围,就加入到队列里,只到最先找到了母牛,此时即找到了最短路径
需要注意的地方:
不可以重复的走已经走过的路,所以需要一个book数组(标记数组)来标记已经走过的路
每一次进入搜索后,需要对队列进行清零,因为上一次搜索时找到最短路径,队列里不一定为空
还有可能母牛在农夫的后面,三种走法中只有一种后退的走法,所以农夫只能一步步后退,找到母牛
AC代码
#include <queue>//队列所用的头文件
#include <cstdio>
#include <cstring>//memset函数在这个头文件里
#include <iostream>
using namespace std;
int n, k;//n是农夫的位置,k是母牛的位置
bool book[100005];//标记数组
struct node{//定义结构体
int place, sum;//place是当前的位置,sum是花费的时间
};
queue<node> q;//定义队列q
node t, m, p;//t是模拟变量,m是起点,p是中间变量,用来存储当前队列最前面的值
void bfs(int n, int k)
{
if(n >= k){ printf("%d\n",n - k); return;}//如果母牛在农夫后面,那么三种走法中农夫只能后退,每次后退一步,所以相差的距离即为所花费的分钟数
q = queue<node>();//清空队列
m.place = n;//起点坐标即农夫的初始位置
m.sum = 0;//此时农夫还没有走,花费的时间为0
q.push(m);//将起点压入队列
memset(book,0,sizeof(book));//清空标记数组
book[n] = 1;//起点标记为已经走过
while(!q.empty()){//只要队列不空,就进行循环
p = q.front();//p用来存储当前队列最前面的值
q.pop();//将队列最前面的弹出
t = p;//t来存储这个值,用来模拟
t.place --;//如果后退一步
if(t.place > 0 && book[t.place] == 0){//后退一步后如果满足条件,没有出这条线,并且这个位置没有走过,那么后退了一步
t.sum ++;//后退一步,花费分钟数+1
if(t.place == k){ printf("%d\n",t.sum); return;}//如果找到了母牛,输出花费的分钟数,bfs函数结束
q.push(t);//在队列里压入这个位置
book[t.place] = 1;//将这个位置标记已经走过
}
t = p;
t.place ++;//如果前进一步
if(t.place <= 100000 && book[t.place] == 0){//前进一步后如果满足条件,没有出这条线,并且这个位置没有走过,那么前进了一步
t.sum ++;//前进一步,花费分钟数+1
if(t.place == k){ printf("%d\n",t.sum); return;}//如果找到了母牛,输出花费的分钟数,bfs函数结束
q.push(t);//在队列里压入这个位置
book[t.place] = 1;//将这个位置标记已经走过
}
t = p;
t.place *= 2;//如果传送到二倍于这个位置的位置
if(t.place <= 100000 && book[t.place] == 0){//到这个位置后如果满足条件,没有出这条线,并且这个位置没有走过,那么就传送到了这个位置
t.sum ++;//传送到这个位置,花费分钟数+1
if(t.place == k){ printf("%d\n",t.sum); return;}//如果找到了母牛,输出花费的分钟数,bfs函数结束
q.push(t);//在队列里压入这个位置
book[t.place] = 1;//将这个位置标记已经走过
}
}
}
int main(void)
{
while(~scanf("%d%d",&n,&k)){bfs(n, k);}//多次输入,进行搜索
return 0;
}