本文涉及知识点

C++贪心
C++二分查找

[蓝桥杯 2022 省 A] 青蛙过河

题目描述

小青蛙住在一条河边,它想到河对岸的学校去学习。小青蛙打算经过河里的石头跳到对岸。

河里的石头排成了一条直线,小青蛙每次跳跃必须落在一块石头或者岸上。不过,每块石头有一个高度,每次小青蛙从一块石头起跳,这块石头的高度就会下降 1 1 1,当石头的高度下降到 0 0 0 时小青蛙不能再跳到这块石头上(某次跳跃后使石头高度下降到 0 0 0 是允许的)。

小青蛙一共需要去学校上 x x x 天课,所以它需要往返 2 x 2x 2x 次。当小青蛙具有一个跳跃能力 y y y 时,它能跳不超过 y y y 的距离。

请问小青蛙的跳跃能力至少是多少才能用这些石头上完 x x x 次课。

输入格式

输入的第一行包含两个整数 n , x n, x n,x, 分别表示河的宽度和小青蛙需要去学校的天数。请注意 2 x 2x 2x 才是实际过河的次数。

第二行包含 n − 1 n-1 n1 个非负整数 H 1 , H 2 , ⋯   , H n − 1 H_{1}, H_{2}, \cdots, H_{n-1} H1,H2,,Hn1, 其中 H i > 0 H_{i}>0 Hi>0 表示在河中与 小青蛙的家相距 i i i 的地方有一块高度为 H i H_{i} Hi 的石头, H i = 0 H_{i}=0 Hi=0 表示这个位置没有石头。

输出格式

输出一行, 包含一个整数, 表示小青蛙需要的最低跳跃能力。

样例 #1

样例输入 #1

5 1
1 0 1 0

样例输出 #1

4

提示

【样例解释】

由于只有两块高度为 1 1 1 的石头,所以往返只能各用一块。第 1 1 1 块石头和对岸的距离为 4 4 4,如果小青蛙的跳跃能力为 3 3 3 则无法满足要求。所以小青蛙最少需要 4 4 4 的跳跃能力。

【评测用例规模与约定】

对于 30 % 30 \% 30% 的评测用例, n ≤ 100 n \leq 100 n100;

对于 60 % 60 \% 60% 的评测用例, n ≤ 1000 n \leq 1000 n1000;

对于所有评测用例, 1 ≤ n ≤ 1 0 5 , 1 ≤ x ≤ 1 0 9 , 0 ≤ H i ≤ 1 0 4 1 \leq n \leq 10^{5}, 1 \leq x \leq 10^{9}, 0 \leq H_{i} \leq 10^{4} 1n105,1x109,0Hi104

蓝桥杯 2022 省赛 A 组 F 题。

贪心+二分查找

二分查找:寻找首端
参数范围:[1,n]
Check(mid):
跳跃能力是y,能否跳跃2x次。
heights 记录各石头的高度,前后各增加一个高度为2x的石头,代表起点和终点。
c[i]记录石头i,能够跳出的次数。c[0]=2x
队列记录c[i-y…i-1]及i。
for i = 1 To N
c[i-1]入队
i- 如果队首元素下标 > y,出队。
当 i1 = min(队首元素的跳出次数,height[i])
队首元素的跳出次数 -= i1 如果为0,出队。
height[i]-=i1
c[i] +=i1
返回值:c.back()==2x
第i块石头的前置位置优先用编号(下标)小的。
时间复杂度:O(nlogn)

代码

核心代码

#include <iostream>
  #include <sstream>
    #include <vector>
      #include<map>
        #include<unordered_map>
          #include<set>
            #include<unordered_set>
              #include<string>
                #include<algorithm>
                  #include<functional>
                    #include<queue>
                      #include <stack>
                        #include<iomanip>
                          #include<numeric>
                            #include <math.h>
                              #include <climits>
                                #include<assert.h>
                                  #include<cstring>
                                    #include <bitset>
                                      using namespace std;
                                      template<class T = int>
                                        vector<T> Read(int n,const char* pFormat = "%d") {
                                          vector<T> ret(n);
                                            for(int i=0;i<n;i++) {
                                            scanf(pFormat, &ret[i]);
                                            }
                                            return ret;
                                            }
                                            template<class T = int>
                                              vector<T> Read( const char* pFormat = "%d") {
                                                int n;
                                                scanf("%d", &n);
                                                vector<T> ret;
                                                  T d;
                                                  while (n--) {
                                                  scanf(pFormat, &d);
                                                  ret.emplace_back(d);
                                                  }
                                                  return ret;
                                                  }
                                                  string ReadChar(int n) {
                                                  string str;
                                                  char ch;
                                                  while (n--) {
                                                  do
                                                  {
                                                  scanf("%c", &ch);
                                                  } while (('\n' == ch));
                                                  str += ch;
                                                  }
                                                  return str;
                                                  }
                                                  template<class INDEX_TYPE>
                                                    class CBinarySearch
                                                    {
                                                    public:
                                                    CBinarySearch(INDEX_TYPE iMinIndex, INDEX_TYPE iMaxIndex) :m_iMin(iMinIndex), m_iMax(iMaxIndex) {}
                                                    template<class _Pr>
                                                      INDEX_TYPE FindFrist(_Pr pr)
                                                      {
                                                      auto left = m_iMin - 1;
                                                      auto rightInclue = m_iMax;
                                                      while (rightInclue - left > 1)
                                                      {
                                                      const auto mid = left + (rightInclue - left) / 2;
                                                      if (pr(mid))
                                                      {
                                                      rightInclue = mid;
                                                      }
                                                      else
                                                      {
                                                      left = mid;
                                                      }
                                                      }
                                                      return rightInclue;
                                                      }
                                                      template<class _Pr>
                                                        INDEX_TYPE FindEnd(_Pr pr)
                                                        {
                                                        INDEX_TYPE leftInclude = m_iMin;
                                                        INDEX_TYPE right = m_iMax + 1;
                                                        while (right - leftInclude > 1)
                                                        {
                                                        const auto mid = leftInclude + (right - leftInclude) / 2;
                                                        if (pr(mid))
                                                        {
                                                        leftInclude = mid;
                                                        }
                                                        else
                                                        {
                                                        right = mid;
                                                        }
                                                        }
                                                        return leftInclude;
                                                        }
                                                        protected:
                                                        const INDEX_TYPE m_iMin, m_iMax;
                                                        };
                                                        class Solution {
                                                        public:
                                                        int Ans(int x, vector<int>& heights)
                                                          {
                                                          heights.insert(heights.begin(), 2 * x);
                                                          heights.emplace_back(2 * x);
                                                          const int N = heights.size();
                                                          auto Check = [&](int mid)
                                                          {
                                                          auto tmp = heights;
                                                          vector<int> c(N);
                                                            c[0] = 2 * x;
                                                            queue<pair<int, int>> que;
                                                              for (int i = 1; i < N; i++) {
                                                              if (c[i - 1] > 0) { que.emplace(c[i - 1], i - 1); }
                                                              while (que.size() && (que.front().second < i - mid)) {
                                                              que.pop();
                                                              }
                                                              int i1 = 0;
                                                              while (que.size() && (i1 = min(tmp[i], que.front().first))) {
                                                              que.front().first -= i1;
                                                              if (0 == que.front().first) { que.pop(); }
                                                              tmp[i] -= i1;
                                                              c[i] += i1;
                                                              }
                                                              }
                                                              return c.back() >= 2 * x;
                                                              };
                                                              return CBinarySearch(1, N).FindFrist(Check);
                                                              }
                                                              };
                                                              int main() {
                                                              #ifdef _DEBUG
                                                              freopen("a.in", "r", stdin);
                                                              #endif // DEBUG
                                                              int n,x;
                                                              scanf("%d%d", &n,&x);
                                                              auto h = Read<int>(n - 1);
                                                                auto res = Solution().Ans(x, h);
                                                                cout << res << std::endl;
                                                                #ifdef _DEBUG
                                                                #endif	
                                                                return 0;
                                                                }

单元测试

int x;
vector<int> h;
  TEST_METHOD(TestMethod11)
  {
  x=1,h = { 1,0,1,0 };
  auto res = Solution().Ans(x,h);
  AssertEx(4, res);
  }

扩展阅读

我想对大家说的话
工作中遇到的问题,可以按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。
学习算法:按章节学习《喜缺全书算法册》,大量的题目和测试用例,打包下载。重视操作
有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注
闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛
失败+反思=成功 成功+反思=成功

视频课程

先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771
如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

posted on 2025-10-21 11:07  ycfenxi  阅读(1)  评论(0)    收藏  举报