洛谷试题之跳石头
https://www.luogu.com.cn/problem/P2678
这题可以根据输出要求
最短跳跃距离的最大值,判断是要使用二分。
二分有一个模板
while(left<=right)
{
int mid=(left+right)/2;
if(check(mid))
{
left=------
}
else{
right=------
}
}
这个check函数里的内容根据不同的题目不同,主要是为了判断这个中间值mid是不是符合要求,如果符合,就将左边界或者右边界根据题目的要求来进行改变。
根据题目要求,要移走M块石头,并且不能移走起点和终点的石头,这时候我们就应该思考,通过不断的二分,判断mid是不是符合题目条件,如果两个石头之间的距离大于mid,那么就说明不需要移走石头,那么我们就跳过这块石头,跳下一块石头,如果两个石头之间的距离小于mid,那么说明我们要移走后面那块石头,同时用一个变量tot来记录移走的石头数目,当遍历了所有石头之后,如果这个tot大于题目中需要移走的石头数m,那么说明移走的石头太多了,也就是mid太大了,这时候主函数里的mid应该就要把上边界right=mid-1;反之,如果小于等于需要移走的石头数,那么说明移走的时候少了或者刚好够,这就说明mid的值太小了,我们就要在主函数里将mid的下边界left=mid+1,通过不断的二分,最终一定会趋于一个值,此时我们输出它就是本题的答案。
下面放代码WZ
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<queue>
#include<stack>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
const int INF= 0x3f3f3f3f;
int l, n, m;
int a[500001];
bool check(int mid)
{int tot = 0;
int pos = 0;
for (int i = 1; i <=n+1;i++)
{
if(a[i]-a[pos]>=mid)
{
pos = i;//跳过石头
}
else{
tot++;//移走石头
}
}
if(tot>m)
return false;
else{
return true;}
}
int main()
{
cin >> l >> n >> m;
for (int i = 1; i <= n;i++)
{
cin >> a[i];
}
a[0] = 0;
a[n + 1] = l;
int left = 0;
int right = l;
while(left<=right)
{
int mid = (left + right) / 2;
if(check(mid))//判断是否符合题意
{
left = mid + 1;//下边界变大
}
else{
right = mid - 1;//上边界减小
}
}
cout << right;;
return 0;
}