vjudge-Catch That Cow
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
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;
}
執行截圖如下