洛谷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]

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