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

传送门:https://www.luogu.com.cn/problem/P2678

非常同意一个观点:二分答案由二分区间和judge函数构成

二分答案,顾名思义,就是找到答案的范围区间,然后在这个区间里面去二分查找最优答案

该题目的答案区间显而易见就是0到L,那么接下来就是judge函数的处理了

可以这样考虑,对于一个答案,我假设它是正确的的,那么要达到满足这个答案的状态我可能需要去移动石头,先不考虑题目中移走石头个数的限制,只要两个石头之间不满足答案,我就移走一块,那在满足答案的时候,我可能移走了超过题目限制的石头。这说明为了这个答案是偏大的,因为我需要移走更多的石头才能达到答案的差值,所以我需要缩短有区间来将答案调小,反之,如果我要移走的石头小于等于题目限制,说明这个答案是可行的,但由于要求的是最大值,我们的答案虽然符合,但也许不是最大,那我就把这个答案及记录下来并缩短左区间查找看是否有更大的答案

上代码

#include<iostream>
#define MAX 50050
using namespace std;
int Array[MAX], L, N, M;
bool Judge(int length)
{
	int now = 0, count = 0;
	//now记录当前在第几块石头
	//count表示在当前答案下需要移走几块石头才能满足
	for (int i = 1; i <= N + 1; i++)
	{
		if (Array[i] - Array[now] < length)count++;
		else now = i;
		//如果前面一块石头跟现在的位置差小于最大值
		//就需要移走这块石头,否则前进,跳到下一块石头
	}
	if (count > M)return false;
	else return true;
	//如果需要移走的石头大于题目给定值
	//说明这个答案一定不能满足条件且偏大,那么
	//就需要缩短右边界来让答案变小一点
	//否则答案满足,但是可能有最优解,缩短左边界
}
int main(void)
{
	cin >> L >> N >> M;
	for (int i = 1; i <= N; i++)
		cin >> Array[i];
	Array[N + 1] = L;
	int left = 0, right = L + 1, mid = 0, ans = 0;
	//答案区间在0到L+1直接
	while (left <= right) {
		mid = (left + right) / 2;
		if (Judge(mid)) { left = mid + 1; ans = mid; }
		//用一个ans变量记录答案是一种好方法,不易错
		else right = mid - 1;
	}
	cout << ans;
	return 0;//完结撒花
}

### NOIP 2015 提高 石头 Python 解题思路 #### 动态规划求解最小踩石子数目 对于给定的独木桥长度以及青蛙跃距离范围,目标是最小化青蛙过河过程中踩到的石子数量。此问题可以通过动态规划来解决。 定义 `dp[i]` 表示到达第 `i` 块石子位置时所踩过的最少石子数[^3]。初始化数 `dp` 的大小为石子总数加一,并设定初始值均为无穷大(表示不可达),除了起点外设为零因为起始处无任何代价。 遍历每一个可能作为新一步起点的位置 `i` 和每一块可至的新位置 `j` ,更新 `dp[j]` 。具体来说,在每次尝试从某一点跃向另一点的过程中,如果该次跃有效,则比较当前记录下的最优方案与此次新增路径哪个更优并据此调整: ```python import sys def min_stones(n, m, stones): INF = float('inf') # 初始化dp表 dp = [INF] * n dp[0] = 0 for i in range(m): # 对于每一颗石子 for j in range(i + 1, n): # 尝试跃到后面所有的石子上去 distance = abs(stones[j] - stones[i]) if L >= distance >= D and dp[i] != INF: dp[j] = min(dp[j], dp[i] + 1) return min([val for idx,val in enumerate(dp) if stones[idx]>=L]) if any(stones>=L for stones in stones[m:]) else "无法完成" n, l, d, m = map(int, input().split()) stones_position = list(map(int, input().strip().split())) print(min_stones(n, l, d, m)) ``` 上述代码实现了基于动态规划算法计算最短路径的思想,其中 `min_stones()` 函数接收四个参数分别为:总共有多少块石子、独木桥全长、允许的最大单步跨度、已知存在几块固定不动的大石子;而输入部分则提供了这些数据的具体数值形式供调用者传入实际测试案例使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值