「青训营 X 码上掘金」主题创作活动-寻友之旅/攒青豆

62 阅读1分钟

当青训营遇上码上掘金

主题 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 个非负整数依次表示柱子的高度,排列后如下图所示,此时均匀从上空向下撒青豆,计算按此排列的柱子能接住多少青豆。(不考虑边角堆积)

image.png 分析题目可以知道,柱子能接的青豆和柱子之间的高度关系有关,对所有的柱子从两边向中间遍历,每次记录当前柱子的高度,例如,用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;
}