题目链接
Description
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
本人BFS启蒙题在此
根据该题经验,快速写出本题的结构体和主函数,并定义了搬运工和检查员
typedef struct {
int sit;//坐标
int time;//深度
}H;
H h1, h2;//搬运工和检查员
//主函数
int main() {
int sit_farmer;//农夫的坐标
int sit_cow;//奶牛的坐标
sit_farmer = read();//读入挂
sit_cow = read();
if (sit_farmer >= sit_cow) {//农夫在奶牛前面,只能后退
Out(sit_farmer - sit_cow);//输出挂输出坐标差值
}
else {
int temp = BFS(sit_farmer, sit_cow);//返回所求的结果
cout << temp;
}
}
我发现其实BFS不是说不能返回值写成void不可,有返回值其实是个好事,直接把层数返回回来岂不方便得多?
然后就是分析操作了,这题比倒可乐方便多了,倒可乐还要考虑溢出不溢出,这里只需要考虑数组别越界就行了,BFS定义的参数依旧是边界(貌似边界其实也分好几层边界,可乐那题的边界既决定了停止搜索的情况,又决定了判断操作合理性的边界(以s->a为例,包括了检查员的s不能为空,还有检查员的s小于等于边界a-检查员a),这题参数的边界只是决定是否停止搜索的,决定操作合理性的只有数组规模)
然后愉快的写出BFS
int BFS(int farmer,int cow) {
h2.sit = farmer;
h2.time = 0;
jud[farmer] = true;
Q.push(h2);
while (!Q.empty()) {
h1 = Q.front();//检查员取物
Q.pop();//取出物件
if (h1.sit == cow) {
return h1.time;
}
//操作1,翻二倍
if(h1.sit*2 <= 200000)//防止越界访问,也是本题操作合理性的边界
if (!jud[h1.sit * 2]) {//2倍坐标没被走过
jud[h1.sit * 2] = true;
h2.sit = h1.sit * 2;//给h2装载货物
h2.time = h1.time + 1;
Q.push(h2);//运输进队列
}
//操作2,前进一步
if(h1.sit+1<=200000)
if (!jud[h1.sit + 1]) {//前一个坐标没走过
jud[h1.sit + 1] = true;
h2.sit = h1.sit +1;
h2.time = h1.time + 1;
Q.push(h2);
}
//操作3,后退一步
if(h1.sit-1>=0)//防止越界访问
if (!jud[h1.sit - 1]) {//后一个坐标没走过
jud[h1.sit - 1] = true;
h2.sit = h1.sit - 1;
h2.time = h1.time + 1;
Q.push(h2);
}
}
return -1; //对本题没必要,因为怎么走都能走到牛那里去
}
然后这题就已经解决掉了
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
typedef long long ll;
inline ll read() {//读入挂
ll c = getchar(), Nig = 1, x = 0;
while (!isdigit(c) && c != '-')c = getchar();
if (c == '-')Nig = -1, c = getchar();
while (isdigit(c))x = ((x << 1) + (x << 3)) + (c ^ '0'), c = getchar();
return Nig * x;
}
inline void Out(ll a)
{//输出挂
if (a < 0)putchar('-'), a = -a;
if (a >= 10)Out(a / 10);//记得这是a>=10,让坑坏了
putchar(a % 10 + '0');
}
typedef struct {
int sit;//坐标
int time;//深度
}H;
H h1, h2;//搬运工和检查员
bool jud[200007];//标记状态是否存在
queue<H>Q;//队列
int BFS(int farmer,int cow) {
h2.sit = farmer;
h2.time = 0;
jud[farmer] = true;
Q.push(h2);
while (!Q.empty()) {
h1 = Q.front();//检查员取物
Q.pop();//取出物件
if (h1.sit == cow) {
return h1.time;
}
//操作1,翻二倍
if(h1.sit*2 <= 200000)//防止越界访问
if (!jud[h1.sit * 2]) {//2倍坐标没被走过
jud[h1.sit * 2] = true;
h2.sit = h1.sit * 2;//给h2装载货物
h2.time = h1.time + 1;
Q.push(h2);//运输进队列
}
//操作2,前进一步
if(h1.sit+1<=200000)
if (!jud[h1.sit + 1]) {//前一个坐标没走过
jud[h1.sit + 1] = true;
h2.sit = h1.sit +1;
h2.time = h1.time + 1;
Q.push(h2);
}
//操作3,后退一步
if(h1.sit-1>=0)//防止越界访问
if (!jud[h1.sit - 1]) {//后一个坐标没走过
jud[h1.sit - 1] = true;
h2.sit = h1.sit - 1;
h2.time = h1.time + 1;
Q.push(h2);
}
}
return -1;
}
int main() {
int sit_farmer;
int sit_cow;
sit_farmer = read();
sit_cow = read();
if (sit_farmer >= sit_cow) {//农夫在奶牛前面,只能后退
Out(sit_farmer - sit_cow);
}
else {
int temp = BFS(sit_farmer, sit_cow);
cout << temp;
}
}
总结下BFS解题步骤
1、明确怎么定义结构体,应该都有个表示深度的成员
2、明确操作和边界,注意退出搜索的边界和决定操作有效的边界(先判断是否能操作,然后操作,最后判断是否有效)
3、还是要记住队列要用初状态初始化
以上我愿称之为BFS三连:结构体、边界、队列初始化
4、看看要不要返回值(最好还是带上返回值)