十三届蓝桥杯省赛c++A组题解
青蛙过河(链接)
转换问题:
1.青蛙往返x次相当于去2x次
2.青蛙能否在y的跳跃能力下过河转换成是否满足长度为y的区间石头高度和不小于2x
转换2的思路:
每一个的长度为y的区间在每一次过河中一定会经过
反证法:若某个长度为y的区间没有被经过,那么一定有一步跳越了y+1步以上的距离
有了这个启发,就接着想问题的转换,转换是等价的,有了必要性得证明充分性
长度为y的区间石头高度和大于等于2x则青蛙能完成2x次过河
设经过每块石头的次数为a[i]
构造法:
1.第一步很特殊,我们只能落入\([1,y]\)区间,那么我们可以有\(\sum_{i=1}^{y} a[i]=2x\)
2.对于接下来的\([y+1,2y]\)区间,我们有区间[2,y+1]....[y,2y-1]可以得到\(\sum_{i=k}^{y+k-1} H[i]\geq2x\),
则有
每个方程右边下标的位置能跳到左边的位置,区间\([1,y]\)能被区间\([y+1,2y]\)完美接纳
因为可以构造
同理能递推\([ky+1,(k+1)y]\)
3.递推终止在尾部长度L小于y的区间
设前一个长度为y的区间为\([my+1,(m+1)y]\)
\([my+1,my+L]\)都能按照构造法跳跃到\([(m+1)y+1,(m+1)y+L]\),而\([my+L+1,(m+1)y]\)都能跳到岸边
接着\([(m+1)y+1,(m+1)y+L]\)也能跳到岸边
证毕!
问题解决
y越大越容易满足2x次过河,满足单调性,属于二分情况,直接对y二分搜索得到最小满足2x次过河的y
代码
#include <iostream>
using namespace std;
int sH[100005]={0};
int n, x;
bool check(int y)//y能够满足2x次跳跃返回true
{for (int i = 1; i <= n-y+1;i++)if(sH[i+y-1]-sH[i-1]<2*x)return false;return true;
}
int main(void)
{// 区间长度y就是答案,把对岸边当作石头cin >> n >> x;for (int i = 1; i <n; i++){cin >> sH[i];sH[i] += sH[i - 1];//构造前缀和}sH[n] = sH[n - 1] +(int)1e9;int l = 1, r = n;while (l<r){int mid = l+((r-l)>>1);if(check(mid))//右边的一定满足r = mid;//偏左elsel = mid + 1;}cout << l;return 0;
}