POJ 3278 Catch that cow 广度优先搜索

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 - 1 or + 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.

题意:给定两个整数n和k,通过 n+1或n-1 或n*2 这3种操作,使得n==k。输出最少的操作次数。

  广度优先搜索实现方法(非递归):

 1.设置一个队列Q,从顶点出发,遍历该顶点后让其进队;

 2.出队一个顶点元素,求该顶点的所有邻接点(对应于此题即三种走法),

    对于没有遍历过的邻接点遍历之,并 让其进队;

 3.若队空则停止,否则继续第2步。

注意,在N>K时只能通过不断N-1才能到达K,可直接返回N-K;N=K时,返回0。

利用STL库:

//Memory 820K	Times 157MS
#include<iostream>
#include<queue>
#include<utility>
using namespace std;
const int maxn=100010;
int N,K;
bool vis[maxn];

int bfs()
{
	if(N>=K) return N-K;//直接返回结果
	queue<pair<int,int> > que;//队列记录坐标及对应的步数
	vis[N]=true;
	que.push(make_pair(N,0));
	while(!que.empty())
	{
		int cur=que.front().first,step=que.front().second;
		que.pop();
		int next[3];
		next[0]=cur+1,next[1]=cur-1,next[2]=cur*2;//三种状态转移方式
		for(int i=0;i<3;i++)
		{
			if(next[i]>=0&&next[i]<maxn&&!vis[next[i]])//剪枝:下一步坐标在范围内且之前没有经过
			{
				if(next[i]==K)	return step+1;//到达终点则返回结果
				vis[next[i]]=true;
				que.push(make_pair(next[i],step+1));
			}
		}
	}
}
int main()
{
	cin>>N>>K;
	cout<<bfs()<<endl;
	return 0;
}

利用模拟队列(所需存储空间较大,处理速度快):

//Memory: 1056K		Time : 16MS
#include<iostream>

using namespace std;

const int maxn = 100010;
struct node {
	int num;//坐标
	int step;//步数
	node(int n = 0, int s = 0)
	{
		num = n; step = s;
	}
}queue[maxn];//模拟队列数组
bool vis[maxn];


int bfs(int n, int k)
{
	if (n >= k) return n - k;	//特例
	//memset(vis, false, sizeof(vis));
	//memset(queue, 0, sizeof(queue));
	int head, tail;
	head = tail = 0;
	queue[tail++] = node(n, 0);//初始节点
	vis[n] = true;
	while (head != tail)
	{
		node temp = queue[head++];
		int next;
		for (int i = 0; i < 3; i++)
		{
			if (i == 0) next = temp.num + 1;
			if (i == 1) next = temp.num - 1;
			if (i == 2) next = temp.num * 2;
			if (next<0 || next>maxn) continue;
			if (!vis[next])
			{
				if (next == k) return temp.step + 1;
				vis[next] = true;
				queue[tail++] = node(next, temp.step + 1);
			}
		}
	}
}
int main()
{
	int n, k;
	cin >> n >> k;
	cout << bfs(n, k) << endl;
	return 0;

}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值