当青训营遇上码上掘金
题目简介
寻友之旅
小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。
步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1
公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)
请帮助小青通知小码,小青最快到达时间是多久?
输入: 两个整数 N 和 K
输出: 小青到小码家所需的最短时间(以分钟为单位)
思路分析
经典的算法问题,作者本来打算使用动态规划来处理此题,但由于小青可以后退一格使得我们的递推公式无法得出,若只能前进不能后退,动态规划将是最好的解决方法。如今我们只能考虑暴力解决问题,但105的数据量我们需要一些技巧,这时搜索算法登场了。
广度优先搜索BFS
利用队列先进先出的特性,让起始位置进入队列,轮换的执行后退前进与翻倍操作。由于我们执行一轮操作时,消耗的步数都是相同的,所以所有的执行步骤等价,最先到达目的地的即为最优方案。那么问题就转换成了记录每一步的位置与步数,有序的执行后退前进和翻倍操作。
C++实现如下
#include <iostream>
#include <queue>
using namespace std;
typedef pair<int, int> PII;
queue<PII> q;
int main()
{
int n, k;
cin >> n >> k;
q.push({n, 0});
int res = 0;
while(q.size())
{
PII t = q.front();
q.pop();
if(t.first < 0)
continue;
else if(t.first == k)
{
res = t.second;
break;
}
for(int i = 0; i < 3; i++)
{
switch(i)
{
case 1: q.push({t.first-1, t.second+1}); break;
case 2: q.push({t.first+1, t.second+1}); break;
default: q.push({t.first*2, t.second+1});
}
}
}
cout << res;
return 0;
}
在此时,我们使用res接收最优结果,静静等待即可。
总结
计算机最擅长计算,而编码的目的是为了在得出相同结果的情况下减少计算的次数。这也正是算法学习的巧妙之处。