本文涉及知识点
[蓝桥杯 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 n−1 个非负整数 H 1 , H 2 , ⋯ , H n − 1 H_{1}, H_{2}, \cdots, H_{n-1} H1,H2,⋯,Hn−1, 其中 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 n≤100;
对于 60 % 60 \% 60% 的评测用例, n ≤ 1000 n \leq 1000 n≤1000;
对于所有评测用例, 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} 1≤n≤105,1≤x≤109,0≤Hi≤104 。
蓝桥杯 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++**实现。
浙公网安备 33010602011771号