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 ",f[k]-1); } }
小结:错误的点就是没有考虑到遍历时f数组小于零时的越界情况。在入队时处理而不是在出队时特判。