Time Limit: 2000ms
Memory Limit: 32768KB
64-bit integer IO format: %I64d Java class name: Main
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.
AC代码(15ms 1900KB):
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <cstring>
#include <queue>
using namespace std;
int dis[100005];
const int INF=0x3f3f3f3f;
int m,n;
queue<int> q;
int bfs(int sx)
{
int xx;
memset(dis,INF,sizeof(dis));
while (!q.empty()) q.pop();
q.push(sx);
dis[sx]=0;
while(!q.empty()&&xx!=n)
{
int x=q.front();
q.pop();
xx=x+1;
if(xx>=0&&xx<=100000&&dis[xx]==INF)
{
dis[xx]=dis[x]+1;
q.push(xx);
// cout<<x<<" "<<dis[x]<<" "<<xx<<" "<<dis[xx]<<endl;
}
if(xx==n)break;
xx=x-1;
if(xx>=0&&xx<=100000&&dis[xx]==INF)
{
dis[xx]=dis[x]+1;
q.push(xx);
// cout<<x<<" "<<dis[x]<<" "<<xx<<" "<<dis[xx]<<endl;
}
if(xx==n)break;
xx=x*2;
if(xx>=0&&xx<=100000&&dis[xx]==INF)
{
dis[xx]=dis[x]+1;
q.push(xx);
// cout<<x<<" "<<dis[x]<<" "<<xx<<" "<<dis[xx]<<endl;
}
if(xx==n)break;
}
cout<<dis[n]<<endl;
}
int main()
{
while(cin>>m>>n)
{
bfs(m);
}
return 0;
}
在写的过程中遇到的新知识点:
①在不用结构体只用队列时,queue<>括号中应该填int或double数据的类型
②清空队列的三种方式(使用了方法二,对我来说最容易理解):
方法一
直接用空的队列对象赋值
queue<int> q1;
q1 = queue<int>();
方法二
遍历出队列
while (!q.empty()) q.pop();
方法三
使用swap,这种是最高效的,定义clear,保持STL容器的标准。
void clear(queue<int>& q) {
queue<int> empty;
swap(empty, q);
}
经过了多次尝试,以下为出现WA以及改进的过程:
①不使用循环输入的话会WA(不知道为什么),绝对没有endl重复换行。
②使用循环输入时一定要在每一次调用bfs时清空队列,不然同一个队列会混乱:对于xx与x的关系操作时,x并不是理想中的x,所以当xx找到n时也可能由于dis[xx]还是INF导致输出错误的值,不过倒是可以知道0x3f3f3f3f的值啦。
③在队列的while循环中,可以不加xx!=n这个判断条件,因为如果是的话在循环内部已经break过,不会返回到循环条件上。不加的话时间更短(我也很震惊可以快到0ms,只出现了一次,后来复制粘贴的代码也不能AC快到0ms,偶然状况吧)。
条件加多了更麻烦,加了xx!=m之后cout时不能用dis[xx]因为当数字过大时有可能某一种情况遍历到起点就停了,可是还没有到达终点。
④很奇怪,这道题可以重复换行,不会PE,也就是除了在bfs函数里加endl,在主函数中再加一个endl也还是对的。
⑤如果当数字很大时才会出现错误的话真的输出验证会跑很久很久,所以最终还是想了想循环上会出什么错。