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