#include 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; }