主题 3:寻友之旅

80 阅读2分钟

当青训营遇上码上掘金

主题 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;
}