2018.1.27【HDU - 2717 】解题报告(BFS)

5 篇文章 0 订阅

Catch That Cow

Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 17820    Accepted Submission(s): 5260


Problem 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
 

Recommend
teddy

【题目大意】

一个人想用最短的时间去抓住一头牛,牛不会动,人的移动规则是:下一次移动可以移动到X+1位置,X-1位置,或者2*X位置(X为当前位置坐标),现在给定人和牛的坐标,求人抓到牛所需要的最短时间(次数)

【解题思路】

很直接的广搜,搜索规则可以理解成三个direction,+1,-1,*2;最后可以加上一点处理(不知道算不算剪枝)因为坐标横大于0,那么若牛的初始坐标值小于人,那么无需广搜可以得到最短次数即坐标值之差(每次左移一个单位),另由于广搜深度增加,每次搜索的量会很大,可以加入判断搜索到结果时立即跳脱循环。

【解题代码】

#include <queue>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include<algorithm>
using namespace std;
const int maxn=100001;  
int n,m; 
bool vis[maxn]; // 访问标记
int dir[3]; 
//struct State // BFS 队列中的状态数据结构
//{
//	int x;
//	int Step_Counter; // 搜索步数统计器
//};
queue <int> q;
int step[maxn];
bool CheckState(int X) // 约束条件检验
{
//	int X=now.x;
	if(X>=0&&X<=100000&&!vis[X]) // 满足条件	
	{
//		printf("next X=%d, step=%d\n",X,now.Step_Counter+1);
		return 1;
	}	
	else // 约束条件冲突
		return 0;
}

void bfs(int st)
{
	int now,next; // 定义2个状态,当前和下一个
	q.push(st);
	step[st]=0;
	vis[st]=true; // 访问标记
	while(!q.empty())
	{
		now=q.front(); // 取队首元素进行扩展
		if(now==m) // 出现目标态,此时为Step_Counter 的最小值,可以退出即可
		{
			printf("%d\n",step[now]);
			return;
		}
		//按照规则搜索下一组数
		//两种形式,一种左右,一种倍乘。 
		dir[0]=-1;dir[1]=1;dir[2]=now;
		int flag=0; 
		for(int i=0;i<3;i++)
		{
			next=now+dir[i];
//			printf("check X=%d, step=%d\n",next,step[now]+1); 
			if(next==m)//剪枝,立即跳出循环
			{
				while(!q.empty()) q.pop();
				step[next]=step[now]+1;
				q.push(now);
				q.push(next);
				break;
			}
			if(CheckState(next))
			{
				step[next]=step[now]+1;
				vis[next]=true;		//不要忘了标记已访问
				q.push(next);
			}
		}
		q.pop(); // 队首元素出队
	}
 	return;
}

int main()
{
//	freopen("in.txt","r",stdin);
	while(~scanf("%d%d",&n,&m))
	{
		while(!q.empty()) q.pop();
		memset(vis,0,sizeof(vis));
		memset(step,0,sizeof(step));
		if(n>=m) printf("%d\n",n-m);
		else bfs(n);
	}
}
【收获与反思】

使用模板里的结构时

出现了两次MLE,不知道是什么个情况,有待检查

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值