洛谷 [NOIP2015 提高组] 跳石头 题解

题目传送门:P2678 [NOIP2015 提高组] 跳石头

题解

这道题目明显就是要用二分答案来求。题目中说“即最短跳跃距离的最大值。”看到最短距离最大
化,就说明我们的二分答案就要登场了.

二分答案

平时我们解决问题一般是求解,但还有一种叫做试解,其中就有二分试解.但是,二分答案是有限制的!所求序列必须具有单调性。二分答案的时间复杂度约为 Θ ( l o g n ) . \Theta(logn). Θ(logn).

left, right, mid

可以编写一个check函数来判断当前解是不是正解.如果是正解

那么就去右半区查询.为什么?因为这个序列本身是递增的而且

题目要求最大的值,所以当然要去右半区找.

否则就去左半边找,为什么?

这个数组本来就是递增的,有因为当前解不是正解,所以比它大的值

也不可能是正解,那么只能去左半边找的.

注意事项

切记! a n a_n an 并不是终点,所以要把 a n + 1 a_{n+1} an+1 的值设为 l l l.

代码

#include<bits/stdc++.h>
using namespace std;
int l, n, m, a[500005], ans;
bool check(int x) {
	// cnt:移走石块数目 i:下一块石头的编号  now:当前石头编号 
	int cnt = 0, i = 0, now = 0;
	while (i < n + 1) { // n不是终点! 
		i++;
		if (a[i] - a[now] < x) // 如果当前值小于mid 
			cnt++; // 把它移走 
		else 
			now = i; // 否则先走过来 
	}
	if (cnt > m) return 0; // 如果搬多了,那么说明它不是正解 
	else return 1;
}
int main() {
//	freopen("stone.in", "r", stdin);
//	freopen("stone.out", "w", stdout);
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin >> l >> n >> m;
	for (int i = 1; i <= n; i++)
		cin >> a[i];
	a[n+1] = l; // a[n]不是终点 
	int le = 1, ri = l; // 左边为1,右边为l 
	while (le <= ri) { // 二分标准循环 
		int mid = (le + ri) / 2; // 计算mid值 
		if (check(mid)) { // 是否是正解 
			ans = mid; // 是的话,更新答案 
			le = mid + 1; // 去找右半边有没有更好的答案 
		}
		else
			ri = mid - 1; // 否则去左半边找 
	}
	printf("%d", ans);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值