POJ3278-Catch That Cow

题目链接
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、看看要不要返回值(最好还是带上返回值)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值