二分相关

二分答案


 基本模板 
在一个有序数组中二分查找一个值 k

 1 // 在一个单调数组里面二分查找某一个值 k
 2 int n, k;
 3 int a[MAXN];
 4 
 5 void solve() {
 6     int lb = -1, ub = n;
 7     while (ub - lb > 1) {
 8         int mid = (lb + ub) / 2;
 9         if (a[mid] >= k) {
10             ub = mid;
11         } else {
12             lb = mid;
13         }
14     }
15     printf("%d
", ub);
16 }

例题分析

POJ1064 

假定一个解并判断是否可行

题目:有 N 条绳子,长度分别为L。如果从他们中切割出 K 条长度相同的绳子的话,这 K 条绳子每条最长能有多长。答案保留到小数点后两位

解:C(x) = 可以得到 k 条长度为 x 的绳子 = floor((Li / x)的总和是否大于 k )

代码如下:

注意在程序判定中,我们的解的范围要求小数点后两位,因为 1 次循环可以将区间的范围缩小一半,100 次循环则可以达到 10-30 的精度范围。除此之外,也可以把中止条件设为像 (ub - lb)> EPS 这样,指定一个区间的大小

 1 int N, K; 
 2 double L[MAXN];
 3 
 4 bool C(double x) {
 5     int num = 0;
 6     for (int i = 0; i < N; i++) {
 7         num += (int)(L[i] / x);
 8     }
 9     return num >= K;
10 }
11 
12 void solve() {
13     // 初始化解的范围
14     double lb = 0, ub = INF * 1.0;
15 
16     // 重复循环,直到解的范围足够小
17     for (int i = 0; i < 100; i++) {
18         double mid = (lb + ub) / 2;
19         if (C(mid))
20             lb = mid;
21         else
22             ub = mid;
23     }
24     printf("%.2f
", floor(ub * 100) / 100);
25 }
26 
27 int main() {
28 #ifndef ONLINE_JUDGE
29     freopen("input.txt", "r", stdin);
30 #endif
31     scanf("%d %d", &N, &K);
32     for (int i = 0; i < N; i++) scanf("%lf", &L[i]);
33     solve();
34     return 0;
35 }

POJ 2456 

最大化最小值

题目:

农夫约翰打了一间有 N 间牛舍的小屋。牛舍排在一条线上,第 i 号牛舍在 x_i 的位置。但是他的 M 头牛对小屋很不满意,因此经常互相攻击。约翰为了防止牛之间的互相伤害,因此决定把每头牛都放在离其他牛尽可能远的牛舍。也就是要最大化最近的两头牛之间的距离。

解:

C(d)= 可以安排牛的位置使得最近的两头牛的距离不小于 d。则问题转化为求最大的 d

贪心:

对牛舍的位置进行排序;

把第一头牛放入 $x_0$ 的牛舍;

如果第 i 头牛放入了 $x_j$ 的话,第 $i+1$ 头牛就要放入满足 $x_j+d<=x_k$ 的最小的 $x_k$ 中

 1 int N, M;
 2 int x[MAXN];
 3 
 4 bool C(int d) {
 5     int last = 1;
 6     for (int i = 1; i < M; i++) {
 7         int crt = last + 1;
 8         while (crt <= N && x[crt] - x[last] < d) {
 9             crt++;
10         }
11         if (crt == N + 1) return false;
12         last = crt;
13     }
14     return true;
15 }
16 
17 void solve() {
18     sort(x + 1, x + 1 + N);
19     int lb = 0, ub = INF;
20     while (ub - lb > 1) {
21         int mid = (ub + lb) / 2;
22         if (C(mid))
23             lb = mid;
24         else
25             ub = mid;
26     }
27     printf("%d
", lb);
28 }
29 
30 int main() {
31 #ifndef ONLINE_JUDGE
32     freopen("input.txt", "r", stdin);
33 #endif
34     scanf("%d %d", &N, &M);
35     for (int i = 1; i <= N; i++) scanf("%d", &x[i]);
36     solve();
37     return 0;
38 }
原文地址:https://www.cnblogs.com/romaLzhih/p/11619504.html