1. 程式人生 > 其它 >vjudge-Catch That Cow

vjudge-Catch That Cow

技術標籤:原創佇列資料結構演算法bfs

vjudge-Catch That Cow

題目

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.

中文版
‎農夫約翰已經被告知一頭逃逸的奶牛的位置,並希望立即抓住她。他從數字行上的‎‎點 N‎‎ (0 ≤ ‎‎N‎‎ ≤ 100,000) 開始,而牛在同一數字行上從‎‎點 K‎‎ (0 ≤ ‎‎K‎‎ ≤ 100,000) 開始。農民約翰有兩種交通方式:步行和傳送。‎

‎* 步行:FJ 可以在‎‎一分鐘內從任何點‎‎ ‎‎X‎‎移動到點‎‎X ‎‎- 1 或‎
‎X = 1 * 傳送:FJ 可以在一分鐘內從‎‎任何點 X‎‎移動到點 2 × ‎‎X。‎

‎如果牛,不知道它的追求,不移動,多久農民約翰要找回它?‎

‎輸入‎
‎第 1 行:兩個空格分隔的整數‎‎:N‎‎和‎‎K‎
‎輸出‎
‎第1行:用最少的時間,在幾分鐘內,農民約翰需要抓住逃亡的牛。‎
‎示例輸入‎
5 17
‎樣品輸出‎
4
‎提示‎
‎農民約翰到達逃逸牛的最快方式是沿著以下道路移動:5-10-9-18-17,這需要4分鐘。‎

這裡我們使用廣度優先搜尋(BFS)來寫
廣度優先搜尋: 在廣度優先搜尋演算法中,解答樹上結點的擴充套件是按它們在樹中的層次進行的。首先生成第一層結點,同時檢查目標結點是否在所生成的結點中,如果不在,則將所有的第一層結點逐一擴充套件,得到第二層結點,並檢查第二層結點是否包含目標結點,……,對層次為n+1的任一結點進行擴充套件之前,必須先考慮層次完層次為n的結點的每種可能的狀態。因此,對於同一層結點來說,求解問題的價值是相同的,可以按任意順序來擴充套件它們。通常採用的原則是先生成的結點先擴充套件。因此儲存佇列主要用佇列這種資料結構

BFS的虛擬碼
將初始結點壓入佇列
標記該結點
while 佇列不為空
{
取出隊首結點
判斷隊首結點是否為答案
若為答案則退出
若不為答案
{
迴圈遍歷改結點的情況
砍斷該狀態是否可行
若狀態不可行 —繼續判斷下一個狀態
若狀態可行
標記該狀態
將狀態壓入佇列
}
}
以下是有解釋程式碼

#include <bits/stdc++.h>//這裡使用了萬能頭,我的vjudge過不了,我重新換了個
using namespace std;
int N,K;
const int maxn=100000;//最大長度
int vis[maxn+10];
struct step//建立一個叫step的結構體
{
	int x;//位置 
	int steps;//到達x所需的步數
	step(int xx,int s):x(xx),steps(s){} 
	//結構體step的建構函式
	//Step(int xx, int s){
    //x = xx;
   //steps = s;
   // }
};
queue <step> q;//佇列,即open表 
int main()
{
	cin>>N>>K;
	memset(vis,0,sizeof(vis));//使用memset函式給vis賦值

	//BFS虛擬碼套進去
	q.push(step(N,0)); //初始結點壓入佇列
	vis[N]=1;//標記該結點
	
	while(!q.empty())
	{
		step s=q.front();//取出首結點
		if(s.x==K)//判斷是否為答案,就是我們需要尋找的K
		{
			cout<<s.steps<<endl;//若為答案就輸出 
			return 0;
		}
		else //如果不是答案 遍歷該結點的情況,轉移到下一個狀態 
		{
			if(s.x-1>=0&&!vis[s.x-1])//判斷 -1 的狀態是否可行 
			{
				q.push(step(s.x-1,s.steps+1));//壓入佇列
				vis[s.x-1]=1;//標記狀態
			}
			if(s.x+1<=maxn&&!vis[s.x+1])//判斷 +1 的狀態是否可行 
			{
				q.push(step(s.x+1,s.steps+1));
				vis[s.x+1]=1;
			}
			if(s.x*2<=maxn&&!vis[s.x*2])//判斷 *2 的狀態是否可行 
			{
				q.push(step(s.x*2,s.steps+1));
				vis[s.x*2]=1;
			}
			q.pop();//刪除隊首元素
		 } 
		 
	}
	return 0;
}

以下是沒有解釋的程式碼

#include <bits/stdc++.h>
using namespace std;
int N,K;
const int maxn=100000;
int vis[maxn+10];
struct step
{
	int x;
	int steps;
	step(int xx,int s):x(xx),steps(s){} 
};
queue <step> q;
{
	cin>>N>>K;
	memset(vis,0,sizeof(vis));
	q.push(step(N,0));
	vis[N]=1;
	
	while(!q.empty())
	{
		step s=q.front();
		if(s.x==K)
		{
			cout<<s.steps<<endl;
			return 0;
		}
		else 
		{
			if(s.x-1>=0&&!vis[s.x-1])
			{
				q.push(step(s.x-1,s.steps+1));
				vis[s.x-1]=1;
			}
			if(s.x+1<=maxn&&!vis[s.x+1])
			{
				q.push(step(s.x+1,s.steps+1));
				vis[s.x+1]=1;
			}
			if(s.x*2<=maxn&&!vis[s.x*2])
			{
				q.push(step(s.x*2,s.steps+1));
				vis[s.x*2]=1;
			}
			q.pop();
		 } 
		 
	}
	return 0;
}

執行截圖如下
在這裡插入圖片描述