小言_互联网的博客

广搜入门——(Catch That Cow)poj2378

346人阅读  评论(0)

题目(题目传送门

Catch That Cow
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 147593 Accepted: 45350
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.
Source

USACO 2007 Open Silver
[Submit] [Go Back] [Status] [Discuss]

分析

牛一共有三种方式变化位置,刚开始想用贪心或者动态规划做,贪心肯定是不对的,大家可以看看这个题中给的样例是怎么来的,
5-10-9-18-17,对于10-9这个操作,他竟然往后退了一步,其实10离17还很远,应该还是往左走,不应该往右走,但是9*2=18就非常接近了,这才是最优的方法。也就是说不能单独去选择移动距离最大的方法
对于动态规划是可以的
比较简单的是广搜这个方法,这个题简单是因为这个是线性的搜索,实在一个x坐标轴上的,一般的搜索都是一个图可以上下左右走。

关于深搜

深搜其实比广搜简单,对于广搜,我们顺着一条路走到底,如果这条路走不动了,就返回上一步(return),从上一步换一个方向走,所以递归调用函数挺复杂的。
广搜就是每走到一个点,就把这个点能走的方向都走一遍,并把这些能够到达的点存到队列中,所以用到了队列这个数据结构,特点先进先出

看下面这个图
A B C D E 1
F G H I J 2
K L M N O 3
P Q R S T 4
U V W X Y 5
以M为起点,可以上下左右移动,所以可以到达HRLN,这个就是所要找的队列,然后下一个点是H,它可以到达的点是CMGI,此时注意M这个点,刚才我们已经走过了,所以要把M去掉(我们如何判断这个点走没走过呢,就用book数组进行标记),再一个要把H这个点从队列里去除,因为H这个点能到达的点都走过一遍了,这个点已经没有利用价值了,所以此时的队列就是
RLNCGI,注意顺序,下一个要走的是R这个点,走完以后的队列是LNCGIWQS,就这样可以把一个图进行模拟搜索。

代码

#include<stdio.h>
#include<stdlib.h>
#include<queue>
#include<algorithm>
#include<string.h>
const int maxn=100000+6;
using namespace std;
queue<int>q;//队列 
int book[maxn];//标记走没走过 
int fa[maxn];//走到这个点是第几步 
int main()
{
	int n,k,b,sum=0;
	scanf("%d%d",&n,&k);
	q.push(n);
	book[n]=1;
	if(n!=k)//判断要去的点就是此时的点的时候不需移动 
	{
	
	while(!q.empty())
	{
		b=q.front();//队首元素
		if(book[b+1]==0&&b+1<maxn)//向右加一 
		{
			fa[b+1]=fa[b]+1;
			if(b+1==k)
			{
				break;
			 } 
			q.push(b+1);
			book[b+1]=1;
		}
		
		if(b-1>=0&&book[b-1]==0)//向左走一步 
		{
			fa[b-1]=fa[b]+1;
			if(b-1==k)
			{
				break;
			 } 
			q.push(b-1);
			book[b-1]=1;
		}
		
		if(b*2<maxn&&book[b*2]==0)//瞬移 
		{
			fa[b*2]=fa[b]+1;
			if(b*2==k)
			{
				break;
			 } 
			q.push(b*2);
			book[b*2]=1;
		}
	    
		q.pop();//这个点利用完了扔掉 
		
	} 
}
	
	printf("%d\n",fa[k]);
	return 0;
 } 

易错点

1.因为可以-1,所以注意母牛的坐标要>=0;因为你标记时用到了数组,数组里面不能有负值
2.因为有+1操作,也有*2操作,所以一定要判断数组不要越界啊!


转载:https://blog.csdn.net/weixin_44554979/article/details/101303902
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场