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

题目传送门

题面

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

河里的石头排成了一条直线,小青蛙每次跳跃必须落在一块石头或者岸上。不过,每块石头有一个高度,每次小青蛙从一块石头起跳,这块石头的高度就会下降 1,当石头的高度下降到 0 时小青蛙不能再跳到这块石头上(某次跳跃后使石头高度下降到 0 是允许的)。
小青蛙一共需要去学校上
x 天课,所以它需要往返 2x 次。当小青蛙具有一个跳跃能力 y 时,它能跳不超过 y 的距离。

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

前置题目

可以先去看一看这道题

看完这道题之后,不难发现(显而易见的),两道题几乎一模一样 (就是不知道为什么青蛙过河明明是进阶版的确是绿题) ,青蛙过河只不过是在这道题的基础上加了一个二分

分析

前置题目的思路我也讲一下

算了还是引用大佬的题解罢

  
先说结论:

最多通过的青蛙的数量就是每个长度为 l 的区间中石头数量的最小值。

我们考虑一段长度为 l 的区间,

因为青蛙最多跳 l 的距离,

不难想到,每只青蛙都一定会在这个区间落下至少一次。

因为一定可以从另一个石子数大于等于 n 的区间跳过来,

所以这样取出的答案是可行的。

那么我们就得到了结论:

最多通过的青蛙的数量就是每个长度为 l 的区间中石头数量的最小值。

青蛙过河分析

有了前置题目,我们就可以把题目转化为求一个最小的数y使得有2x只青蛙能跳过河(差不多就是前置题目倒过来)

那这样就可以轻易的想到用二分的方法

关于可二分性

其实这个不难说明,假设 y1 < y2,倘若青蛙在y1时能跳过河,那么青蛙在y2的时候就一定可以跳过去(可以理解成y2包含y1)

二分范围

很显然我写这个是为了水字数

青蛙想跳过河,那么青蛙的最小跳跃范围至少要是1,最大的自然就是一步跳到和对岸也就是n

代码实现

check函数

既然已经有了前置题目,那我们只需要把前置题目的代码复制过来缝合一下就好了

bool check(int l){
	int cnt = INF;//赋为一个很大的数 跟大佬的rp一样高
	for(int i = l+1; i <= n; i++){
		cnt= min(cnt,b[i]-b[i-l]);
	}
	return cnt >= 2*x;
}

然后你满心欢喜的去提交代码

#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1e7+5;
int n, x;
int a[N],b[N];
int ans = INF;
bool check(int l){
	int cnt = INF;
	for(int i = l+1; i <= n; i++){
		cnt= min(cnt,b[i]-b[i-l]);
	}
	return cnt >= 2*x;
}
int main(){
	cin >> n >> x;
	for(int i = 2; i <= n; i++){
		cin >> a[i];
		b[i] = b[i-1] + a[i];
	}
	int l = 1, r = n;
	while(l < r){
		int mid = (l + r) >> 1;
		if(check(mid)){
			r = mid; 
			ans = mid;
		}else{
			l = mid+1;
		}
	} 
	cout << ans << endl;
	return 0;
}

但是却WA了一个点

打油诗一首

我是一只小青蛙,我在洛谷养青蛙。

我让青蛙去上学,青蛙回我WA WA WA。

因为我们在二分的时候没有判断一步跳到的情况的

但是很显然一步到位的情况是绝对存在的

所以我们只需要把ans赋值为n

丑陋的AC代码

#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1e7+5;
int n, x;
int a[N],b[N];
int ans = INF;
bool check(int l){
	int cnt = INF;
	for(int i = l+1; i <= n; i++){
		cnt= min(cnt,b[i]-b[i-l]);
	}
	return cnt >= 2*x;
}
int main(){
	cin >> n >> x;
	ans = n;
	for(int i = 2; i <= n; i++){
		cin >> a[i];
		b[i] = b[i-1] + a[i];
	}
	int l = 1, r = n;
	while(l < r){
		int mid = (l + r) >> 1;
		if(check(mid)){
			r = mid; 
			ans = mid;
		}else{
			l = mid+1;
		}
	} 
		cout << ans << endl;
	return 0;
}
  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
蓝桥杯是一个国内著名的计算机比赛,为了帮助参赛者更好地准备和了解比赛的题型,组委会会公布历年的真题并提供相应的题解。 首先,我们需要了解蓝桥杯是一个综合性的计算机比赛,测试的对象包括计算机基础知识、编程能力以及解决实际问题的能力。 在历年的真题中,参赛者将面临不同类型的题目,包括算法设计与优化问题、数据结构与算法问题、编程题等。其中针对Python B组的题目主要考察的是对Python语言的掌握和应用能力。 题目解答一般会包含以下几个方面的内容: 1. 题目分析与理解:读取题目,理解题目的要求和限制条件。通过仔细分析题目,确定题目的输入与输出,以及问题的核心。 2. 设计解决方案:根据题目要求和限制条件,设计一个合适的解决方案。可以使用合适的算法和数据结构来解决问题,并做出相应的性能优化。 3. 编写代码实现:根据设计的方案编写相应的代码实现。需要注意的是,Python语言有其独特的语法和特性,掌握好这些特性可以更好地完成编程任务。 4. 调试与测试:编写完代码后,需要进行调试和测试。通过运行样例输入和输出,检查代码是否符合题目要求,并且没有逻辑上的错误。 5. 总结与优化:在完成题目解答后,可以进行总结和优化。包括分析算法复杂度、代码风格和可读性等方面,以便在比赛中更好地表现。 在准备蓝桥杯时,可以通过阅读历年的真题和题解来了解比赛的难度和类型,针对性地进行练习和提高。同时也可以参加相关的培训班和讨论活动,与其他参赛者交流经验和技巧。 总而言之,历年蓝桥杯真题的解答对于提高自己的编程能力和应对比赛非常有帮助。通过认真分析和实践,可以更好地理解并掌握Python编程,并在比赛中取得更好的成绩。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bamboo_Day

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值