当青训营遇上码上掘金
主题 3:寻友之旅
小青要找小码去玩,他们的家在一条直线上,当前小青在地点 N ,小码在地点 K (0≤N , K≤100 000),并且小码在自己家原地不动等待小青。小青有两种交通方式可选:步行和公交。
步行:小青可以在一分钟内从任意节点 X 移动到节点 X-1 或 X+1
公交:小青可以在一分钟内从任意节点 X 移动到节点 2×X (公交不可以向后走)
请帮助小青通知小码,小青最快到达时间是多久?
输入: 两个整数 N 和 K
输出: 小青到小码家所需的最短时间(以分钟为单位)
分析题易知,本题可以等效为,一个数为N,每次操作对其进行+-1或者*2,试问多少次操作后N能变为K
这里选择使用bfs,从N开始,复杂度为O(2*k),具体操作如下:每次从队列取出一个pos,判断条件有三种:1.即将访问的位置已经访问过,不入队列 2.即将访问的位置未访问,入列 3.遇到终点k 中途记录下行走距离,遇到终点n结束。
#include<bits/stdc++.h>
using namespace std;
int vis[200005];
int main(){
int N, K;
cin >> N >> K;
queue<int>q;
q.push(N);
vis[N] = 1;
int ans = 0;
while(!q.empty()){
queue<int>p;
while(!q.empty()){
int now = q.front();
q.pop();
if(now == K){
cout << ans; return 0;
}
if(now < K && !vis[now + 1]){
p.push(now + 1);
vis[now + 1] = 1;
}
if(now - 1 >= 0 && !vis[now - 1]){
p.push(now - 1);
vis[now - 1] = 1;
}
if(now < K && !vis[now * 2]){
p.push(now * 2);
vis[now * 2] = 1;
}
}
q = p;
ans ++;
}
}
主题 4:攒青豆
现有 n 个宽度为 1 的柱子,给出 n 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)
分析题目可以知道,柱子能接的青豆和柱子之间的高度关系有关,对所有的柱子从两边向中间遍历,每次记录当前柱子的高度,例如,用l,r代表左右位置,high为当前的柱子高度,则每次遍历:
high=max(high, min(arr[l], arr[r]))
ans += high - min(arr[l], arr[r]))
如果左边高度大于右边高度,r--,否则l++,当l==r时,可输出答案
#include<bits/stdc++.h>
using namespace std;
int list[10000];
int main(){
int n = 0, x;
while(cin >> x)list[n++] = x;
int l = 0, r = n - 1, high = 0;
long long ans = 0;
while(l < r){
high = max(high, min(list[l], list[r]));
ans += high - min(list[l], list[r]);
if(list[l] > list[r])r--;
else ans += high - list[l], l++;
}
cout << ans;
}