洛谷P2678 跳石头 二分

洛谷P2678 跳石头 二分

[题目传送门][https://www.luogu.com.cn/problem/P2678]

题意:笔直的河道中有N块岩石,起点到终点的距离为L,要移走M块,求两两石头间隔最短距离的最大值。

思路:

以最短距离为左端点,以L为右端点进行二分,以每次的MID为最短距离求取需要移走的岩石数K,

若K>m,说明间隔太大,需要移走的岩石数过多,令R=MID-1,向左进行二分;

若K<m,说明间隔太小,需要移走的岩石数过少,K=m时,需要移走的岩石数刚好=m,因为要求取最大值,都应向更大的间距进行尝试,令L(左端点)=MID+1,向右进行二分。

代码:

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const long long mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const double PI = 3.141592;
const int e = 5e5;

int l, n, m;
ll ans, minx;
ll a[e + 5], b[e + 5];

bool jud(ll x){   //获得以mid为最短跳跃距离的最大值,求的需要移走的岩石数
    ll res = 0, num = 0;
    for(int i = 1; i <= (n + 1); i++){
        if(res + b[i] < x){
            res += b[i];
            num += 1;
        }
        else{
            res = 0;
        }
    }
    //若移走岩石数<=m,继续向大的数进行尝试
    if(num <= m) return 1;
    else return 0;
}

int main()
{
    scanf("%d %d %d", &l, &n, &m);
    a[0] = 0;
    minx = a[1] - a[0];  //求间距最小值,不能设为INF,防止m=0,n=0时WA
    for(int i = 1; i <= n; i++){
        scanf("%lld", &a[i]);
        //b数组来储存相邻两石头间距,共n+1项
        b[i] = a[i] - a[i - 1];
        if(b[i] < minx) minx = b[i];
    }
    b[n + 1] = l - a[n];
    ll L = minx, R = l;
    while(L <= R){
        ll mid = (L + R) / 2;
        if(jud(mid)){
            ans = mid;
            L = mid + 1;
        }
        else R = mid - 1;
    }
    printf("%d\n", ans);
    return 0;
}

类似的题目:[洛谷 P1182 数列分段 Section II][https://blog.csdn.net/weixin_43763903/article/details/105275933]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章