题意
小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。
步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1
公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)
请帮助小青通知小码,小青最快到达时间是多久?
输入: 两个整数 N 和 K
输出: 小青到小码家所需的最短时间(以分钟为单位)
作者:青训营官方账号
链接:juejin.cn/post/718775…
来源:稀土掘金
##解法
1.步行可以看作存在X连向X+1和X-1的有向边,公交看作存在X连向2X的有向边,且边权都为1
2.这样就将问题转换为最短路了
3.这时候我们就可以用Dijkstra算法进行求解了
4.由于考虑到边权相等,所以我们可以直接使用bfs算法进行求解,这样的时间和空间复杂度都是O(n)的
5.还有一种特殊情况是可以直接得出答案的,n>=k,由于往回走只有一条路径,所以我们可以很快的得出答案就是n-k
##代码(C++)
1.首先进行初始化
void init(int n,int k){
memset(dp,0x3f3f,sizeof(int)*(max(n,k)+9));
}
2.跑bfs
int query(int n,int k){
if(n>=k) return n-k;
queue<int> p;
int len=max(n,k)+9;
p.push(n),dp[n]=0;
while(!p.empty()){
int x=p.front();
p.pop();
if(x+1<=len&&dp[x+1]>dp[x]+1){
dp[x+1]=dp[x]+1;
p.push(x+1);
}
if(x-1>=0&&dp[x-1]>dp[x]+1){
dp[x-1]=dp[x]+1;
p.push(x-1);
}
if((x<<1)<=len&&dp[x<<1]>dp[x]+1){
dp[x<<1]=dp[x]+1;
p.push(x<<1);
}
}
return dp[k];
}
##总结
由于图的特殊性,我们不需要使用Dijkstra算法,而选用bfs算法,这样能够有效地降低时间复杂度,而且在代码实现上也更加地简单