当青训营遇上码上掘金

68 阅读2分钟

当青训营遇上码上掘金 主题三(寻友之旅)

题目描述

小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。
步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1
公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)

请帮助小青通知小码,小青最快到达时间是多久?
输入: 两个整数 N 和 K
输出: 小青到小码家所需的最短时间(以分钟为单位)

思路分析

问题可以抽象为在一个有向图中从一个节点到另一个节点的最短路问题, 由于其中每条边的权重为1(从一个节点到另一个节点花费的时间为1), 此时就可以进一步简化为bfs问题, 当我们第一次遍历到节点K时, 即是我们最少花费的时间

实现步骤

1. 将小青现在所在的地点pos加入队列

2. 对pos节点的相邻节点pos + 1, pos - 1, 2 * pos(小青一分钟内能走到的节点)进行判断, 如果还未访问过,就将其加入队列,并更新到达该节点所需的时间。此时间即为N节点到该节点所需的最小时间。

3.当遍历到K节点时,即说明我们找到了从N到K所需要的最小时间,此时我们返回该时间, 否则我们返回-1,表明我们没有找到答案

代码实现

#include <iostream>
#include <cstring>
#include <queue>

using namespace std;

const int N = 10010;
int n,k;

int st[N], minute[N];

int bfs() {
	queue<int> q;
	q.push(n);
	st[N] = 1;
	minute[N] = 0;
	
	while(!q.empty()) {
		int pos = q.front();
		q.pop();
		
		if(pos == k)
			return minute[pos];
			
		if(!st[pos - 1]) {
			st[pos - 1] = 1;
			minute[pos - 1] = minute[pos] + 1;
			q.push(pos - 1);
		}
		
		if(!st[pos + 1]) {
			st[pos + 1] = 1;
			minute[pos + 1] = minute[pos] + 1;
			q.push(pos + 1);
		}
		
		if(!st[pos * 2]) {
			st[pos * 2] = 1;
			minute[pos * 2] = minute[pos] + 1;
			q.push(pos * 2);
		}
	}
	return -1;
}

int main()
{
	cin >> n >> k;
	cout << bfs() << endl;
	
	return 0;
 } 

时间复杂度分析

最坏的情况下,我们会遍历所有的节点,所以此时时间复杂度为O(n),但由于数据量较小,故此题可以用该算法解决。