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;
}
运行截图如下