跳石头 题型:二分

124 阅读1分钟

P2678 [NOIP2015 提高组] 跳石头 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

思想

image.png 根据上面的描述,我们可以用二分模板的第二个模板: image.png

说一下怎么去二分:

题目说了想让选手们在比赛过程中的最短跳跃距离尽可能长.那么我们就去枚举最短距离mid,把

#include<bits/stdc++.h>
#define int long long
using namespace std;
int L,n,m;   //河道长度 n个石块 可以移走的石块个数 
const int N=5e5+10;
int a[N];
int ans;

bool check(int x)
{
	int cnt=0;  //记录移走的石块的个数
	int i=0;    //代表下一块石头的编号
	int now=0;    //当前在哪一块石头准备起跳
	
	while(i<n+1)  //n不是终点,n+1才是
	{
	  i++;  
	  if(a[i]-a[now]<x) //x已经是最短跳跃距离了, 小于x就不合法
	    cnt++;  //把当前石块移走,加长跳跃距离	
	  else
	     now=i; //否则说明当前跳跃距离是合法的,我们就跳到当前石块,继续考虑到下一个石块的跳跃距离是否合法	
	} 
	
	//如果按照二分出来的这个跳跃距离来实行最终移动的石头的个数大于m,说明这个mid不是最终答案 
	if(cnt>m) return false;
	else return true; 
}
void solve()
{
	cin>>L>>n>>m;
	
	for(int i=1;i<=n;i++) cin>>a[i];   //读入n个石块距离起点的距离
	
	a[n+1]=L;  //终点石头距离起3点的距离
	
	//二分枚举最短跳跃距离  
	int l=1,r=L;
	while(l<r)
	{
		int mid=l+r+1>>1;
		if(check(mid)) 
		{
			ans=mid;
			l=mid;
		}
		else
		{
		    r=mid-1;	
		} 
	} 	
	cout<<ans<<endl;
}
signed main()
{
	cin.tie(nullptr)->sync_with_stdio(0); 
	solve();
	
	return 0;
}

image.png