POJ 2456 Aggressive cows(二分查詢 最大化最小值)
阿新 • • 發佈:2019-01-31
題意:給出n個牛棚的位置,選擇其中的m個給牛住,使得牛之間的距離的最小值最大。
首先我們可以知道距離的最小值一定產生於相鄰的牛之間,所以要保證相鄰牛之間的距離大於等於這個最小值d。所以把牛棚的位置從小到大排序,然後在最小的那個位置先放一頭牛,再找下一個牛棚放牛,下一個位置和當前的位置間隔必須大於等於d。如果滿足條件,即可以找到m個牛棚給牛住,那麼再嘗試讓d大一點。為什麼每一次都是大於等於d?就算這一輪沒有出現距離剛好為d的情況,那麼下一次一定可以找到一個距離剛好為d'的情況,其中d'就是這輪中距離的最小值,並且這個d'比d更大。由於mid的時候可能就是最終解,所以區間是左閉右開,要把mid包括進來,最後輸出l。
至於為什麼第一頭牛一定是放在位置最小的地方,可以假設如果放在次小的地方,那麼如果最小值只可能被改得更小,或者不變。
#include<cstdio> #include<cstring> #include<cmath> #include<cmath> #include<algorithm> #define N 100010 #define INF 0x3f3f3f3f using namespace std; int n, c, l, r, mid, st, ed, site[N]; bool ok(int x) { st = 0; ed = 0; for (int i = 0; i < c-1; i++) { while (site[ed+1] - site[st] < x && ed+1 < n) ed++; if (ed+1 == n) return false; //原本下一個牛應該放在[0,n-1]中,現在要超過n-1,說明已經沒有地方可以放了 st = ed+1; ed = st; } return true; } int main() { scanf("%d%d", &n, &c); for (int i = 0; i < n; i++) scanf("%d", &site[i]); sort(site, site+n); site[n] = INF; l = 0; r = INF; while (r - l > 1) { mid = (l + r) / 2; if (ok(mid)) l = mid; else r = mid; } printf("%d\n", l); }