当青训营遇上码上掘金

110 阅读3分钟

当青训营遇上码上掘金
这篇文章讲述了第五届青训营主题三的代码创作灵感和过程。

所选主题:寻友之旅

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

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

实现思路

暴力搜索(bfs)

首先看到的第一眼就知道这个题目是关于最短路的,而且由于数据范围只有100000,因此应该可以使用暴力搜索解决,即把所有从小青的n到小码的k的情况都枚举出来,再取这些情况中的最小值。 对于这道题我们可以使用bfs宽搜来解决,bfs算法可以用来求最短路。
对于任意时刻小青和小码的位置有两种情况,一种情况是小码位于小青前面,这就意味着小青要前往小码的位置,肯定是一直朝向的小青步行的,这种情况简单。第二种情况是小码位于小青后面,在小青前往小码的时候可以选择乘坐公交也可以步行,他们的代价都是1。
当小青在某个位置时,分情况讨论,如果小青位置在小码位置及后面,那么他只能步行,一步一步的走到小码位置。反之,小青位置在小码前面,那么他就两个选择,步行或者坐车,在bfs中把这两个选择都模拟出来就行。

时间复杂度分析

因为所有节点只会遍历到一次,所以时间复杂度为O(n)后者O(k),然而n的范围是0~100000,故使用此算法可以在1s之内计算的结果。

最后看看实现的代码

c++

#include<bits/stdc++.h>

using namespace std;

const int N = 100010,M = 300010;

int n,k;
int ans;
bool st[N];
int que[N];
int dist[N];
int hh,tt = -1;

void bfs(){
	st[n] = true;
	que[ ++ tt] = n;
	dist[n] = 0;
	
	int t;
	int distance;
	while(hh <= tt){
		t = que[hh ++ ];
		distance = dist[t];
		
		if(t >= k){
			dist[k] = min(dist[k],distance + (t - k));
			continue;			
		}
		
		if(!st[t + 1]){
			st[t + 1] = true;
			que[ ++ tt] = t + 1;
			dist[t + 1] = distance + 1;
		}	
		
		if(!st[2 * t]){
			st[2 * t] = true;
			que[ ++ tt] = 2 * t;
			dist[2 * t] = distance + 1;
		}
		
	}
	
	ans = dist[k];
}

int main(){
	cin >> n >> k;
	
	memset(dist,0x3f,sizeof dist);
	
	if(n >= k){
		ans = n - k;
		cout << ans;
		return 0;
	} 
	
	bfs();
	
	cout << ans;
	
	return 0;
} 

go

package main

import (
   "fmt"
   "math"
)

const (
   N = 300010
)

var (
   n    int
   k    int
   ans  int
   st   = make([]bool, N)
   que  = make([]int, N)
   dist = make([]int, N)
   hh   = 0
   tt   = -1
)

func bfs() {
   st[n] = true
   tt = tt + 1
   que[tt] = n
   dist[n] = 0

   var t int
   var distance int
   for hh <= tt {
      t = que[hh]
      hh = hh + 1
      distance = dist[t]

      if t >= k {
         dist[k] = int(math.Min(float64(dist[k]), float64(distance+(t-k))))
         continue
      }

      if !st[t+1] {
         st[t+1] = true
         tt = tt + 1
         que[tt] = t + 1
         dist[t+1] = distance + 1
      }

      if !st[2*t] {
         st[2*t] = true
         tt = tt + 1
         que[tt] = 2 * t
         dist[2*t] = distance + 1
      }

      ans = dist[k]
   }
}

func myinit() {
   for i := 0; i < N; i++ {
      dist[i] = 0x3f3f3f3f
   }
}

func main() {
   fmt.Println("请输入n和k")
   fmt.Scanf("%d%d", &n, &k)

   myinit()

   if n >= k {
      ans = n - k
      fmt.Printf("答案为%d", ans)
      return
   }

   bfs()

   fmt.Printf("答案为%d", ans)

   return
}