進擊的奶牛
阿新 • • 發佈:2018-12-22
題面(from luogu)
進擊的奶牛
Farmer John建造了一個有N(2<=N<=100,000)個隔間的牛棚,這些隔間分佈在一條直線上,座標是x1,…,xN (0<=xi<=1,000,000,000)。
他的C(2<=C<=N)頭牛不滿於隔間的位置分佈,它們為牛棚裡其他的牛的存在而憤怒。為了防止牛之間的互相打鬥,Farmer John想把這些牛安置在指定的隔間,所有牛中相鄰兩頭的最近距離越大越好。那麼,這個最大的最近距離是多少呢?
輸入格式:
第1行:兩個用空格隔開的數字N和C。
第2~N+1行:每行一個整數,表示每個隔間的座標。
輸出格式:
輸出只有一行,即相鄰兩頭牛最大的最近距離。
輸入樣例#1:
5 3
1
2
8
4
9
輸出樣例#1:
3
題目分析
這是一到可以很容易看出來的二分題(巨大的查詢範圍可以看出)。
在正常情況下,二分模板都是可以套進去的,但是難點是在對解是否合法的判斷上。
在這一道題目上面,我們可以寫一個子程式來判斷一下,具體的也就是用當前的解,不停的向前面放,如果當前的放不了了,就說明有一個屋子廢了,當然,我們算出最多可以廢幾個屋子,對比一下,即可
到這裡,這一道題就寫完了,
其他的也就是套模板了,這一題是比較適合用while版的二分來寫的
程式碼
#include <bits/stdc++.h> using namespace std; int a[1000009],n,k; bool judge(int x) //判斷函式 { int sum = 0; //當前一個屋子都沒有廢, int now = a[1]; //從第一個開始試 for (int i = 2; i <= n; i++) { if (now + x > a[i]) sum++; //判斷當前的是否合法,也就是當前試了這組解後有沒有佔到後面的房子裡,如果有了,這一組就廢了,當前的得放在後面後面 else //反之,可以放,繼續向前放 now = a[i]; //這是下一個的起點 if (sum > n - k) return false; //判斷是否還有房子可以浪費,沒有了,就說明,這組解,不合法的 } return true; //反之就是合法的 } int main() { cin>>n>>k; for (int i = 1; i <= n; i++) cin>>a[i]; //輸入 sort(a+1,a+n+1); //資料必需有序的 int left = 1; //左界 int right = a[n] - a[1]; //右界 while (left <= right) { int mid = (left + right) / 2; //去中間數 if (judge(mid)) left = mid + 1; //如果這是一組合法的解,我們就像前試探一下,看一看有沒有更優秀的 else //反之 right = mid - 1; //這一組解不合法,就說明偏大了,向前去找 } if (judge(right)) cout<<right; //判斷更優秀的解 else cout<<left; return 0; //完美的結束程式 }
** 菜雞c_uizrp_dzjopkl原創**