04 P3957 跳房子
https://www.luogu.com.cn/problem/P3957
题意
- n个格子,d为机器人每次前进的距离,k为需要达到的目标
- 每一次,机器人可从左到右前进d.
- 也可以画金币 g。让机器人变得灵活
- 其中 如果 g <d 。活动范围为: d-g <= x <= d+g
- 如果 g>d。活动范围为 1<= x <= d+g
想法
- dp+二分
- f(i) 代表走到第i个格子了,最大的分数
- 二分来找到合适的金币数
//P3957 跳房子
// Created by majoe on 2020/6/25.
//https://www.luogu.com.cn/problem/P3957
#include <bits/stdc++.h>
using namespace std;
const int N = 500010;
long long n,d,k;
long long block[N][2];
long long f[N];//dp
//判断是否可以得到k分以上
bool check(int g){
int lb = d - g, rb = d+g;
if(lb <= 0) lb = 1;
memset(f,-127,sizeof(f));//设为很小的负数
f[0]=0;
for (int i = 1; i <= n ; ++i) {
for (int j = i-1; j >= 0 ; --j) {
//两种极端情况
if((block[i][0] - block[j][0])<lb) continue; //如果步伐太大,不能到达
if((block[i][0] - block[j][0])>rb) break; // 如果步伐太小,不能到达
f[i] = max(f[i],f[j] + block[i][1]); // 更新dp
if (f[i] > k )
return true;
}
}
return false;
}
int main(){
cin >> n >> d >>k;
for (int i = 1; i <= n ; ++i) {
int x,s;
cin >> x >> s;
block[i][0] = x ; block[i][1] = s;//输入距离和分数
}
//二分找到,最小的金币数量
int l=1, r=1005;
while (l < r){
int mid = l + r >> 1;
if (check(mid)){
r = mid;
}
else l = mid + 1;
}
cout << l;
return 0;
}