04 P3957 跳房子

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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值