Files
python/TangDou/CSP-J/AcWingTraining/T7/472_2.cpp

70 lines
2.3 KiB
C++
Raw Normal View History

2025-08-30 18:35:01 +08:00
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 500010;
LL dist[N], w[N], f[N]; // 五年OI一场空,不开long long见祖宗
int n, d, k;
// 检查花费g个金币进行改造后,最高得分是否会超过k
bool check(int gold) {
// 机器人能够弹跳的范围[L,R]
int L = max(1, d - gold);
int R = d + gold;
// 注意:这里要初始化为负无穷
memset(f, 0xc0, sizeof f);
f[0] = 0;
for (int i = 1; i <= n; i++) {
// 从i的前一个格子开始,枚举到起点
for (int j = i - 1; j >= i - R; j--) {
// 剪枝,机器人从j号格子加上R还是法到达i号格子
// 那么从j号格子之前的格子也无法到达i号格子
if (dist[j] + R < dist[i]) break;
// 机器人从j号格子加上L还是超过了i号格子
// 那么继续尝试j号之前的格子
if (dist[j] + L > dist[i]) continue;
// 机器人从j号格子可以转移到i号格子
f[i] = max(f[i], f[j] + w[i]);
if (f[i] >= k) return true;
}
}
return false;
}
int main() {
// 加快读入
ios::sync_with_stdio(false), cin.tie(0);
cin >> n >> d >> k;
for (int i = 1; i <= n; i++) cin >> dist[i] >> w[i];
/*
二分金币的数量
二分时候左右端点是什么?
由于我们点的个数是500000个,要求分数的范围是[1,1e9],机器人初始时是2000的弹跳距离,
那么再结合我们花费金币后机器人弹跳范围,我们想要金币花费最少,假设每个点都得走过,
分数和才能达到最值,那么我们计算下来需要花费的平均金币数为2000,但实际上由于每个点的
分数分布不均匀,并且并不需要每一个点都经过,所以我们二分可以将左边界设为0,右边界设
为2010。
*/
int L = 0, R = 2010, ans = -1;
while (L < R) {
// 所有满足条件的情况都在mid的右边区间,
// 搜索右边区间最小值
// 适用二分搜索模板1
int mid = L + R >> 1;
if (check(mid)) {
ans = mid;
R = mid;
} else
L = mid + 1;
}
cout << ans << endl;
return 0;
}