POJ 3278 Catch That Cow[BFS+队列+剪枝]

第一篇博客,格式惨不忍睹。首先感谢一下鼓励我写博客的大佬@Titordong其次就是感谢一群大佬激励我不断前行@Chunibyo@Tiancfq因为室友tanty强烈要求出现,附上他的名字。

Catch That Cow(POJ3278)

BFS入门题,然鹅我还是WA了四五发,因为没注意,位置0是可以访问的。再者就是初始位置在push之后,要标记为已经访问。
图片挺不错,我们地大(武汉)的旖旎风光,放松一下。

题目链接:POJ3278

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

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.

题意:

这个题建立模型,可以理解为在0-maxn的x轴上,农夫在N点,奶牛在K点,有一下三种方式农夫可以改变自己的位置,每次改变花费一分钟,求到达奶牛的位置的最短时间。

题解:

这个题求最短路,可以想到用BFS。
这里复习一下BFS,BFS本质就是搜索,在搜索过程中,为每一个节点分层,到达目标节点,结束搜索,可以确保找到最优解。由于BFS保存结点数目较多,采用队列实现。这个题我的男神郭炜老师的课件用一个结构体保存每一个点的位置和到达该位置的步数,如下,简单明了。

struct node{
int step,pos;
node(int pos=0,int step=0) : pos(pos),step(step){}
};

也可只用一个vis数组,用于判断是否被访问和当前的步数。基本的BFS题。
还有一点对于BFS的多组输入的题,每次vis数组要清空,q队列清空。

代码

#include<cstdio>
#include<cstring>
#include<iomanip>
#include<algorithm>
#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
using namespace std;
//节点拓展,分层,判重。确保找到最优解,但保存节点较多,多数节点需要保存,队列

typedef long long ll;
const int maxn = 100000;
int vis[500000 + 10];
void Bfs(int n, int k)
{
	memset(vis, 0, sizeof(vis));
	queue<int>q;
	while (!q.empty()) q.pop(); //注意调用前要先清空  
	q.push(n);
	vis[n] = 1;
	while (!q.empty())
	{
		int u = q.front(); q.pop();
		if (u== k)//找到目标,结束搜索
		{
			cout << vis[k]-1 << endl;
			return;
		}
		else {
              //这里是大于等于。
			if (u - 1 >= 0 && !vis[u - 1]) {
				q.push(u - 1);
				vis[u - 1] = vis[u]+ 1;//上一个节点的下一层
			}
			if (u + 1<=maxn && !vis[u +1]) {
				q.push(u +1);
				vis[u+1] = vis[u] + 1;
			}
			if (2 * u <= maxn && !vis[2 *u])
			{
				q.push(2 * u);
				vis[2 * u] = vis[u] + 1;
			}

		}
	}
	

}
int main()
{

	int n, k;
	while (cin >> n >> k)
	{
		if (n >= k)cout << n - k << endl;//可以用来加快运行,小的剪枝
		else 
		Bfs(n, k);
	}
	return 0;
}

本题结束啦,ACM之路还没结束......

原文地址:https://www.cnblogs.com/gzr2018/p/9665608.html