River Hopscotch 二分

Every year the cows hold an event featuring a peculiar version of hopscotch that involves carefully jumping from rock to rock in a river. The excitement takes place on a long, straight river with a rock at the start and another rock at the end, L units away from the start (1 ≤ L ≤ 1,000,000,000). Along the river between the starting and ending rocks, N (0 ≤ N ≤ 50,000) more rocks appear, each at an integral distance Di from the start (0 < Di < L).

To play the game, each cow in turn starts at the starting rock and tries to reach the finish at the ending rock, jumping only from rock to rock. Of course, less agile cows never make it to the final rock, ending up instead in the river.

Farmer John is proud of his cows and watches this event each year. But as time goes by, he tires of watching the timid cows of the other farmers limp across the short distances between rocks placed too closely together. He plans to remove several rocks in order to increase the shortest distance a cow will have to jump to reach the end. He knows he cannot remove the starting and ending rocks, but he calculates that he has enough resources to remove up to M rocks (0 ≤ M ≤ N).

FJ wants to know exactly how much he can increase the shortest distance before he starts removing the rocks. Help Farmer John determine the greatest possible shortest distance a cow has to jump after removing the optimal set of M rocks.

Input
Line 1: Three space-separated integers: L, N, and M
Lines 2… N+1: Each line contains a single integer indicating how far some rock is away from the starting rock. No two rocks share the same position.
Output
Line 1: A single integer that is the maximum of the shortest distance a cow has to jump after removing M rocks
Sample Input
25 5 2
2
14
11
21
17
Sample Output
4
Hint
Before removing any rocks, the shortest jump was a jump of 2 from 0 (the start) to 2. After removing the rocks at 2 and 14, the shortest required jump is a jump of 4 (from 17 to 21 or from 21 to 25).

大体题意是说给出河的长度和其中石头的个数,去掉其中的几块石头,使得两块石头的最小间距最大。

题目的思路比较抽象,首先是用到贪心和二分的思想,进行排序时,需要注意第一块和最后一块石头是省略了的,在这里需要补上,石头总数也会变化。调整之后,遍历一遍数组找出最短的间距,之后用函数进行运算。

函数的运算比较抽象,首先选取最短间距和最大间距和的一半作为二分的比较值,用count记录当前情况下去掉的石头数,s和e则用来表示石头的间距,如果石头间距小于mid,就去掉一块石头让最小间距进行变大,如果以当前mid为标准进行调整需要去掉的石头数满足题意,那么说明最小间距还可以继续扩大,此时所有间距已经都大于mid了,于是将low置为mid+1,如果石头数不满足题意,说明不能够通过调整石头数来使得最小间距扩大到mid,只能将high缩小,让最小间距扩大到相对较小的mid,直到最小间距大于了最大间距,这时循环结束,将最大间距返回主函数输出即可。
AC代码

#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
int l,m,n;
int num[50005];
int fun(int high,int low)
{
	while(low<=high)
	{
		int mid=(low+high)/2;
		int count=0;
		int s=0;
		int e=1;
		while(e<n)
		{
			if(num[e]-num[s]>=mid) 
				s=e;
			else 
				count++;
			e++;
		}
		if(count>m)
			high=mid-1;
		else
			low=mid+1;
	}
	return high;
}
int main()
{
	int high,low;
	cin>>l>>n>>m;
	for(int i=1;i<=n;i++)
		cin>>num[i];
	num[0]=0;
	num[n+1]=l;
	n=n+2;
	sort(num,num+n);
	high=l;
	low=num[1]-num[0];
	for(int i=1;i<n;i++)
		low=min(low,num[i]-num[i-1]);
	cout<<fun(high,low)<<endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43849505/article/details/87482762
今日推荐