洛谷P2678 [NOIP2015 提高组] 跳石头

P2678 [NOIP2015 提高组] 跳石头 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

这道题运用了贪心+二分(贪心做题时候更多凭借感觉,证明很难而且时间成本高,更多靠题感)

难点是我们应该拿什么进行二分

经过多次尝试和参考积累的经验,我们不难想到要将结果进行二分(这道题弄懂之后就会想到了)

若最大的最短跳跃距离为x, 那么我们就需要把石头之间距离小于x的石头移走

统计移走石头的个数进行判断,进而就知道应该往左还是往右二分,套用二分模板即可

这里还有一个核心巧妙的点是before变量的使用,可以从代码中体会

#include <iostream>
#include <algorithm>
using namespace std;
int a[50010];
int s, n, m;

int main()
{
	cin >> s >> n >> m;
	for (int i = 0; i < n; i++) cin >> a[i];
	
	//把可能的答案进行二分 
 	int l = 1, r = s, mid, i;
 	while (l < r)
 	{
 		mid = l + r + 1 >> 1; //下面有l=mid 避免死循环这里要+1 
 		int cnt = 0, before = 0; //cnt记录移走了多少石头, before记录上一个石头到起点的距离
		  
 		for (i = 0; i < n; i++) //枚举每个石头 
 		{
 			if (mid + a[i] > s) break; //如果再跳mid距离就超过总距离 那么直接break (主要判断最后一个石子到终点的距离) 
 			
 			if (a[i] - before < mid) cnt++; //两石头的距离小于mid 则移走 
 			else before = a[i]; //否则记录before 
		}
		
		cnt += n - i;//如果break了 就把i后面的是石头全部移走 
		
		if (cnt <= m) l = mid;
		else r = mid - 1; //二分模板 
	}
	
	cout << l;
	return 0;
}

类似做法的题目 洛谷P3853 [TJOI2007]路标设置 、 洛谷P1182 数列分段 Section II

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值