CF965D 青蛙过河
1 CF965D 青蛙过河
2 题目描述
时间限制 \(1s\) | 空间限制 \(256M\)
有很多只青蛙想过河。河的宽度为 \(w\),但是青蛙最远只能跳 \(𝑙\),\(𝑙<𝑤\)。青蛙也可以跳的比 \(𝑙\) 更近。但不能跳得更远。青蛙准备踩着石头过河。石头与河岸的距离为整数。青蛙所在的河岸距离 \(𝑖\) 的位置有 \(𝑎_𝑖\) 个石头。每只石头只能被一只青蛙踩一次,然后就会淹没在水中。如果青蛙只能踩着石头过河,那么最多有多少只青蛙可以过河?
3 题解
这道题的解法十分容易:对于所有的长度为 \(k\) 的区间,找到其中拥有石头总数最少的区间,该区间的石头总数即是答案。下面我来证明一下这个解法的最优性和可行性。
最优性:由于青蛙无论如何都会经过这个区间,而可以经过这个区间的青蛙数等于这个区间的石头数,所以该区间的石头数即为能经过青蛙数量的最大值。
可行性:对于某个固定位置 \(x\) 来说,我们假设其所有石头上都有青蛙。此时我们可以让这里的所有青蛙都跳到 \(x+l\),而中间部分的青蛙数不变,此时的总青蛙数就是 \(min(a_x, a_{x+l}) + \sum_{i = x+1}^{x+l-1}\limits a_i\)。将后面的大式子直接代入前面的 \(min\),得到的就是 \(min(\sum_{i = x}^{x+l-1} \limits a_i, \sum_{i = x+1}^{x+l} \limits a_i)\),也就是说,对于这两个区间,我们最多可以跳的青蛙数就是这两个区间石头数的最小值。我们此时再将 \(x+1\) 当作 \(x\),继续向下推进,答案就是所有区间的最小值,因此,该构造方案可行。
4 代码(空格警告):
#include <iostream>
using namespace std;
const int N = 1e5+10;
int w, l, ans;
int a[N], sum[N];
int main()
{
ans = 0x3f3f3f3f;
cin >> w >> l;
for (int i = 1; i <= w-1; i++) cin >> a[i], sum[i] = sum[i-1] + a[i];
for (int i = 1; i <= w-l; i++) ans = min(ans, sum[i+l-1] - sum[i-1]);
cout << ans;
return 0;
}