Catch That Cow
题目大意:FrammerJohn找奶牛,给出n和k。FJ在n处。每次他可以向左移动一格、向右移动一格或者移动到自己当前格子数乘2的地方。求FJ最少移动多少次。其中,FJ和Cow在数轴上。
注释:$1<=n,k<=10^5$。
想法:又是一道bfs裸题。就是通过简单的bfs来找寻最优解。其中,先遍历到的点在后面重新遍历时,所得到的步数一定是更劣的。所以,每个点我们只需要更新一次。我们通过f数组记录f[i]表示从n到i的最小步数。然后,我们可以不另开bool数组,只需要通过判断f数组是否有值即可。这里有一个小技巧,就是我们将f[n]=1,然后输出答案时输出f[k]-1.这样就可以避开n点的错误重新遍历的情况。
最后,附上丑陋的代码... ...
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
int n,k;
int f[200010];
inline void bfs()
{
queue<int>q;
int x;
q.push(n);
f[n]=1;//小技巧
while(!q.empty())
{
x=q.front();
q.pop();
if(x+1<=2*k&&!f[x+1])
{
f[x+1]=f[x]+1;
q.push(x+1);
}
if(x-1>=0/*这里非常重要,搜索中我们习惯在入队时就将不满足题意者去除,而不是在出队时特判*/&&!f[x-1])
{
f[x-1]=f[x]+1;
q.push(x-1);
}
if(x*2<=k*2&&!f[x*2])
{
f[x*2]=f[x]+1;
q.push(x*2);
}
}
return;
}
int main(void)
{
while(~scanf("%d%d",&n,&k))
{
memset(f,0,sizeof f);
bfs();
printf("%d\n",f[k]-1);
}
}
小结:错误的点就是没有考虑到遍历时f数组小于零时的越界情况。在入队时处理而不是在出队时特判。

京公网安备 11010502036488号