[题]跳房子 #单调队列优化(伪)

题目

洛谷题目
ACwing题目

放弃单调队列优化了,又长又臭有难搞,还不如直接剪枝来得快。

#include 
#include 
#include 

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

你可能感兴趣的:(算法,c++,题)