河中跳房子(二分

每年奶牛们都要举办各种特殊版本的跳房子比赛,包括在河里从一块岩石跳到另一块岩石。这项激动人心的活动在一条长长的笔直河道中进行,在起点和距离起点 L 远的终点各有一块岩石 (1 ≤ L ≤ 10^9)。在起点和终点之间,有 N 块岩石 (0 ≤ N ≤ 50000),每块岩石与起点的距离分别为 Di (0 < Di < L)。

在比赛过程中,奶牛轮流从起点出发,尝试到达终点,每一步只能从一块岩石跳到另一块岩石。当然,实力不济的奶牛无法抵达终点,在河中间就退出比赛了。

农夫约翰为他的奶牛们感到自豪并且年年都观看了这项比赛。但随着时间的推移,看着其他农夫的胆小奶牛们在相距很近的岩石之间缓慢前行,他感到非常厌烦。他计划移走一些岩石,使得从起点到终点的过程中,最短的跳跃距离最长,跳到终点的距离不计入。他可以移走除起点和终点外的至多 M 块岩石 (0 ≤ M ≤ N)。

请帮助农夫约翰确定:移走这些岩石后,最短跳跃距离的最大值是多少?

输入
第 1 行包含以单个空格分隔的三个整数 L, N, M。

第 2 到 N + 1 行,每行一个整数,表示每个岩石与起点的距离。不会有两个岩石出现在同一个位置。

输出
输出一个整数,即最短跳跃距离的最大值。

示例输入
25 5 2
2
14
11
21
17
示例输出
4
提示
在移除位于 2 和 14 的两块岩石之后,最短跳跃距离达到了最大值 4 (从 17 到 21,或从 21 到 25)。

解题思路
1)起点和终点也是石头,它们之间有N个石头
2)移除的时候只能移除N个石头中的M个,起点和终点的石头是不能移除的
3)奶牛是一块石头一块石头的跳的!!
4)a[i]是每个岩石与起点的距离(我老是忘了
我们是用二分法去推求最长可能的最短跳跃距离
假设最大的最短跳跃距离是d 那么与a[i]的距离小于d的都要被移除 暂定最开始的d=mid=(l+r)/2 即全程的一半
然后以这个标准进行岩石的筛选
以起点为基点,如果从基点到第一块岩石(先sort一遍排个序)的距离小于mid,就把第一块移除掉 统计被移除石头的ans++,然后就是第二块,如果从基点跳到第二块石头的距离还小于d,那就把第二块也给移除掉,nas++
就这么找下去,直到找到一个超过mid的,把它作为基点,再继续遍历下去,逐渐移除石头
就这样筛选完之后 剩下的没被移除的石头中,它们之间的距离一定是大于mid的 ,然后再来判断下ans与m的大小,
ans<=m 说明当前移除的石头还没有达到上限 也就是在筛选过程中的mid值过小啦 那就让l往右移动下,因为要找最优解嘛
ans>m 说明移动的石头超过上限了 也就是mid值过大 那就让l往左移动下

代码如下

#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e5;
int a[maxn];
int n,m,h;
int judge(int mid)
{
	int i;
	int ans=0,k=0;
	for(i=1;i<=n+1;i++)
	{
		if(a[i]-k<mid)
		  ans++;
		else
		  k=a[i];
	}
	if(ans>m)
	  return 0;
	else
	  return 1;
}
int main()
{
	int i;
	int l,r;
	int ans;
	cin>>h>>n>>m;
	for(i=1;i<=n;i++)
	  cin>>a[i];
	a[n+1]=h;//终点的那块石头
	sort(a+1,a+n+2);
	l=1;
	r=h;
	while(l<=r)
	{
		int mid=(l+r)/2;
		if(judge(mid))//去掉的石头<=m个 
		{
			ans=mid;
			l=mid+1;
		}
		else
		{
			r=mid-1;
		}
	}
	cout<<ans<<endl;
	return 0;
}

有的人直接输出的mid 然后不对。。我们需要时刻记录mid的 因为在一直寻找最优解,mid也一直在变 如果在mid符合条件的时候不记录下来 它可能会变成一个不符合的 最后循环终止 输出的也是一个不符合的

啊啊啊终于写完了 太恶心心了

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值