当青训营遇上码上掘金,青训营高质量的课程立刻就会和码上掘金强大的代码编辑产生反应,制造出1+1>2的奇妙效果
主题 3:寻友之旅
小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。 步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1 公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)
请帮助小青通知小码,小青最快到达时间是多久?
输入: 两个整数 N 和 K 输出: 小青到小码家所需的最短时间(以分钟为单位)
思路
首先我们观察可以得出,这是一个最短路径问题,并且,每一条边权值相同
那我们可以用BFS(广度优先搜索)来解决
因为在 BFS 中,我们使用了数据结构中的队列(queue),我们知道队列的特性是 FIFO(First In First Out),也就是先进先出。正是这个 FIFO 特性,保证了我们第一个到达目标节点一定是最短路径
过程如下:
首先观察可以得出,当
n>=k时,不能坐公交(除了[0,0]),只能走路,因此可以直接特判返回n-k维护
d[i]和q[i]数组
d[i]记录从起点到i点的距离,并且当d[i]=-1时,表示这个i点还没有被搜索过;队列
q[i]则记录接下来要搜索的点,队空时结束搜索每次取队头结点
t作为当前起点,尝试三种走法:ntx= [t+1,t-1,t*2],然后当目的地点在范围内(nxt<=k)并且这个点没有被搜索过(d[nxt]==-1),那么可以进行距离更新,然后ntx入栈直到
t==k,说明k点已经被搜索过了,可以直接结束搜索然后返回结果d[k]
代码如下:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5;
int d[N+1]; //存距离
int que[N+1]; //存将要走的点
int bfs(int n,int k){
int hh=0,tt=0;
que[0]=n;//从n开始
memset(d,-1,sizeof(d)); //初始化为-1 表示还未走过
d[n]=0;//点n已经走过
while(hh<=tt){ //队列不空时继续搜
auto t=que[hh++];//每次取队头
if(t==k){//到达目的地
return d[k];
}
for(int i=0;i<=2;i++){//三种走法
int nxt;
if(i==0) {
nxt=t+1;
} else if(i==1) {
nxt=t-1;
} else if(i==2) {
nxt=t*2;
}
if(d[nxt]==-1&&nxt<=N){
d[nxt]=d[t]+1;//距离更新
que[++tt]=nxt;
}
}
}
return d[k];
}
int main(){
int n,k;
cin>>n>>k;
if(n>=k){
cout<< n-k;
return 0;
}
cout<<bfs(n,k);
return 0;
}