当青训营遇上码上掘金-寻友之旅

137 阅读2分钟

题意

小青要找小码去玩,他们的家在一条直线上,当前小青在地点 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算法,这样能够有效地降低时间复杂度,而且在代码实现上也更加地简单