当青训营遇上码上掘金
这篇文章讲述了第五届青训营主题三的代码创作灵感和过程。
所选主题:寻友之旅
小青要找小码去玩,他们的家在一条直线上,当前小青在地点 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
}