牛客算法周周练10 E-跳石头 二分搜索

牛客算法周周练10 传送门

题意、题解和代码都在下面,个人觉得解题思维过程写挺详细的
题目描述
一年一度的“跳石头”比赛又要开始了!
这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石。组委会已经选择好了两块岩石作为比赛起点和终点。在起点和终点之间,有 N 块岩石(不含起点和终点的岩石)。在比赛过程中,选手们将从起点出发,每一步跳向相邻的岩石,直至到达终点。
为了提高比赛难度,组委会计划移走一些岩石,使得选手们在比赛过程中的最短跳跃距离尽可能长。由于预算限制,组委会至多从起点和终点之间移走 M 块岩石(不能移走起点和终点的岩石)。

输入描述:

输入文件第一行包含三个整数 L,N,M,分别表示起点到终点的距离,起点和终点之间的岩石数,以及组委会至多移走的岩石数。 接下来 N
行,每行一个整数,第 i 行的整数 Di(0 < Di < L)表示第
i块岩石与起点的距离。这些岩石按与起点距离从小到大的顺序给出,且不会有两个岩石出现在同一个位置。

输出描述:

输出文件只包含一个整数,即最短跳跃距离的最大值。

示例1
输入

25 5 2
2
11
14
17
21

输出

4

题意:从起点0,到终点L中,有n块石头,你需要移走m块石头,使得相邻两块石头的间距的最小值最大。

题解:对总长度L进行二分搜索,每次二分选择出一个长度mid,判断是否有大于等于m个点相邻的一对点距离小于mid,
若有,则证明这个距离是如何符合答案的某个解(但你还需要再进行二分,因为你不知道这个mid是否属于原数组,且你需要选择出相邻两块石头的间距的最小值最大,所以只有l=r才能保证符合),说明现在的mid偏小,所以你需要稍微增大二分的长度mid,故可改变左边的长度l=mid+1
若否,则说明你现在选择的mid偏大,所以你需要稍微缩小二分的长度mid,故可改变右边的长度r=mid
当l=r,当选择出最优解。

#pragma GCC optimize(2)
#include 
#define ll long long
#define endl  '\n'
using namespace std;
const int mod=1e9+7;
const int MAX=1e6+7;
 ll a[MAX];
int main()
{
 	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
 	ll L,n,m;
 	cin>>L>>n>>m;
 	for(ll i=1;i<=n;i++)
 	cin>>a[i];
 	a[n+1]=L;
	int l=1,r=L+1,ans=0,mid=0;
	while(l<r)
	{
		 mid=(l+r)/2;
		int temp=0,cnt=0;
		for(int i=1;i<=n+1;i++){
			if(a[i]-temp<mid)cnt++;
			else temp=a[i];
		}
		if(cnt>m){
			r=mid;
		}
		else{
			ans=mid;
			l=mid+1;
		}
	} 
 	cout<<ans;
}

你可能感兴趣的:(牛客题解)