题目
洛谷题目
ACwing题目
放弃单调队列优化了,又长又臭有难搞,还不如直接剪枝来得快。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
const int N = 500010;
int n, d, k;
LL dist[N], w[N], f[N];
//检查花费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 >= 0; 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()
{
scanf("%d%d%d", &n, &d, &k);
for(int i = 1; i <= n; i ++)
scanf("%lld%lld", &dist[i], &w[i]);
//R的大小可以通过x/n来确定,平均距离为2000
int L = 0, R = 20000, 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;
}