当青训营遇上码上掘金
主题 3:寻友之旅
小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。
步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1
公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)
请帮助小青通知小码,小青最快到达时间是多久?
输入: 两个整数 N 和 K
输出: 小青到小码家所需的最短时间(以分钟为单位)
题目链接:juejin.cn/post/718775…
分析: 每个点有三条路径可走,x-1,x+1,2x,然后新生成的三个点,同样每个点也有三条路可走,只需BFS出所有情况,当第一次遍历到K这个位置时就是最快到达的情况。
代码需要注意的地方:考虑特殊情况,n>=k,便只能一直选择步行.并且要用visit数组标记一下已经走过的点,避免超时.时间复杂度O(K-N),最坏的情况是一直步行,也就是循环K-N次
代码解释Node记录每个点,index表示当前位置,distance表示走过的时间。 在遍历每个点的时候还要判断该点是否已经走过且该点需要大于0.
#include<bits/stdc++.h>
using namespace std;
struct Node {
int index;
int distance;
Node(int index,int distance):index(index),distance(distance) {
}
};
int main(void) {
int n,k;
cin>>n>>k;
if(n>=k) {
cout<<n-k;
return 0;
}
queue<Node> q;
map<int,bool> visit;
int ans=0;
q.push({n,0});
visit[n]=true;
while(!q.empty()) {
Node cur=q.front();
q.pop(); //对头出队,并开始遍历该元素对应的情况
if(cur.index==k) {
cout<<cur.distance;
break;
}
// 如果当前位置已经大于k,只能步行x-1
else if(cur.index>k) {
int nextpos=cur.index-1;
if(!visit[nextpos]&&nextpos>=0) {
visit[nextpos]=true;
q.push({nextpos,cur.distance+1});
}
} else {
int next[3];
next[0]=cur.index-1;
next[1]=cur.index+1;
next[2]=cur.index*2;
for(int i=0; i<=2; i++) {
if(!visit[next[i]]&&next[i]>=0) {
visit[next[i]]=true;
q.push({next[i],cur.distance+1});
}
}
}
}
return 0;
}