2018.1.27【HDU - 2717 】解題報告(BFS)

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,不知道是什麼個情況,有待檢查

發佈了40 篇原創文章 · 獲贊 1 · 訪問量 6262
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章