当青训营遇上码上掘金
主题3:寻友之旅(BFS解法)
题面:
小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。
步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1
公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)
解法: BFS很经典的一道题目,虽然题面看到过很多个版本,但是一看到题目本质就觉得既视感太强了2333。
变量解释: maxn:最大可能结点(题目条件1e5,再加5防爆)
t[maxn]:到达每个节点的最小时间
队列next:下一个bfs的对象,bfs队列经典用法
广度优先搜索(也称宽度优先搜索,缩写BFS)是连通图的一种遍历策略。它的思想是从一个顶点开始,辐射状地优先遍历其周围较广的区域(一生二,二生三,三生万物……)。从起点开始,经过多轮搜索达到终点,此时记录的轮数就是到终点的最短路程,很多最短路径算法就是基于广度优先的思想成立的。这道题也一样,而且远没有复杂的图那样难办。
总体思路就是从n开始,bfs遍历每个可到达的点。新到达的是当前起点的时间+1,然后把新点放到队列里用于下一轮bfs。
一点细节补充: 这里用memset设成-1而不是0是为了防止n==k的情况,根据是否-1可以根据这个判断这个点到过没有,到过就不更新了。当然设成0然后用一个特判n是否等于k来防止特例也是可以的。 if (2a < maxn && t[2a] == -1)像这个位置要把判断是否超过数组范围放在前面,免得运行错误。
#!/jcode/lang/cpp https://xitu.github.io/jcode-languages/dist/lang-cpp.json
#include<iostream>
#include<utility>
#include<algorithm>
#include<string>
#include<vector>
#include<queue>
#include<sstream>
#include<stack>
#include<string.h>
#include<queue>
#include<unordered_map>
using namespace std;
const int maxn = 100005;
int t[maxn];
int bfs(int &n,int &k)
{
queue<int> next;
memset(t, -1, sizeof(t));
next.push(n);
t[n] = 0;
while (!next.empty())
{
int a = next.front();
next.pop();
if (2*a < maxn && t[2*a] == -1)
{
t[2*a] = t[a] + 1;
if (2*a == k)return t[2*a];
next.push(2*a);
}
if (a + 1 < maxn && t[a + 1] == -1)
{
t[a + 1] = t[a] + 1;
if (a + 1 == k)return t[a + 1];
next.push(a + 1);
}
if (t - 1 >= 0 && t[a - 1] == -1)
{
t[a - 1] = t[a] + 1;
if (a - 1 == k)return t[a - 1];
next.push(a - 1);
}
}
}
int main()
{ int n, k;
cin >> n >> k;
cout << bfs(n,k) << endl;
return 0;
}