洛谷P2768

二分真的好难/(ㄒoㄒ)/~~!

首先看题,题目中我们可以知道选手跳跃最短距离的最大值,所以我们可以使用二分。

判断是否需要二分可以看题目中是否有类似求最短距离的最大值或者最大距离的最小值。

那么本题怎么进行二分呢

我们可以以整段距离为一个大区间,然后二分取其中间值,用其中间值来暂时当作一个最大的最小跳跃距离,以此来求需要搬掉几块石头。如果石头搬多了那么说明我们选择的值太大,搬少了,说明我们选择的值太小。最后两个端点就可以确定同一个值了。

废话不多说,上代码:

#include <bits/stdc++.h>
#define LL long long

using namespace std;
const int N = 5 * 1e4 + 10;
//typedef long long LL;
int l, n, m, ans;
int d[N];
//二分模板一般时比较固定的,但是难就难在中间的check函数上


inline int read()//快读不解释
{
	int sum = 0;
	char ch = getchar();
	while (ch > '9' || ch < '0') 
		ch = getchar();
	while (ch <= '9' && ch >= '0')
		sum = sum * 10 + ch - 48, ch = getchar();
	return sum;
}

bool check(int x)//x为中间值
{
	int cnt = 0;//判断移去的石头的数量
	int next = 0;//下一块石头的位置
	int now = 0;//运动员所处的位置
	while (next < n + 1)
	{
		next++;
		if (d[next] - d[now] < x)//如果两块石头的位置小于我们需要的x,则可以搬掉next所在的这个石头,运动员位置保持不变来判断下一块。
		{
			cnt++;//搬掉了一块石头
		}
		else
			now = next;//中间距离超过了我们现在的最大的最小距离,则不能搬,运动员到这个石头的位置
	}
	if (cnt > m)//看看搬的石头是多还是少
		return false;
	else
		return true;
}

int main()
{
	l = read(), n = read(), m = read();
	for (int i = 1; i <= n; ++i)
	{
		d[i] = read();
	}
	d[n + 1] = l;
	int rl = 1, r = l;//rl为左端点,r为右端点
	while (rl <= r)//二分模板
	{
		int mid = (rl + r) / 2;
		if (check(mid))//值太小,搬少了或者搬得刚刚好
		{
			ans = mid;//暂时存到这里,看看有没有更好的解
			rl = mid + 1;
		}
		else//值太大,搬少了
			r = mid - 1;
	}
	cout << ans << endl;//最后的答案
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值