POJ - 3278 Catch That Cow (kuangbin - 简单搜索)

题目描述(已转换成中文)

  农夫知道一头牛的位置,想要抓住它。农夫和牛都于数轴上 ,农夫起始位于点 N(0<=N<=100000) ,牛位于点 K(0<=K<=100000) 。
  农夫有两种移动方式:
  1、从 X移动到 X-1或X+1 ,每次移动花费一分钟;
  2、从 X移动到 2*X ,每次移动花费一分钟;
假设牛没有意识到农夫的行动,站在原地不动。最少要花多少时间才能抓住牛?

输入格式

  一行: 以空格分隔的两个字母: N 和 K

输出格式

  一行: 农夫抓住牛需要的最少时间。

输入输出样例
输入

5 17

输出

4

题目链接

分析:

  这道题是最基本的bfs(广度优先搜索)题目,现在说一说bfs函数,首先定义一个数据类型为int的队列,再定义一个vis数组,vis[i]用来标记坐标i是否已经被压入过队列,定义一个a数组,a[i]记录步长,就是农夫到达坐标i时所用的最短时间。
  一开始,先把农夫目前的坐标n压入队列,此时a[n] = 0;接着如果队列不为空的话,每次弹出队首元素,对队首元素进行处理:分别对应题意的三种操作,三个坐标得到的对应新坐标q(必须不能超过边界),如果满足条件(!vis[q])则压入队列,并用a[q]记录坐标q的最短步长,并且标记已经被压入过队列(vis[q] = 1),当农夫到q的位置正好是牛k的位置的时候,返回并输出a[q]即可。

这道题需要注意的地方:

  n代表的是农夫的位置,k代表的是牛的位置,因为农夫要是在牛的右边,他要追到牛的话只能一步一步往左走,所以当输入的n >= k,直接输出n - k即可,如果n < k再调用bfs函数求出抓住牛需要的最少时间。

代码如下:

#include<iostream>
#include<string.h>
#include<queue>
#define N 100005 
using namespace std;
typedef long long LL;
int a[N], vis[N];
queue <int> s;
int bfs(int n, int k){
	int p, q, i;
	a[n] = 0;
	vis[0] = 1;
	s.push(n);
	while(!s.empty()){
		p = s.front();
		s.pop();
		for(i = 0; i < 3; i++){
			if(i == 0) q = p + 1;
			else if(i == 1) q = p - 1;
			else q = 2 * p;
			if(q >= N || q < 0) continue;
			if(!vis[q]){
				s.push(q);
				vis[q] = 1;
				a[q] = a[p] + 1;
			}
			if(q == k) return a[q];
		}
	}
}
int read(){
	int x, f = 1;
	char ch;
	while(ch = getchar(), ch < '0' || ch > '9') if(ch == '-') f = -1;
	x = ch - '0';
	while(ch = getchar(), ch >= '0' && ch <= '9') x = x * 10 + ch - 48;
	return x * f;
}
int main(){
	int n, k;
	n = read();
	k = read();
	if(n >= k) printf("%d", n - k);
	else printf("%d", bfs(n, k));
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值