zoukankan      html  css  js  c++  java
  • 二分相关

    二分答案


     基本模板 
    在一个有序数组中二分查找一个值 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 }
  • 相关阅读:
    MashupGoogle Map API与饭否API的整合应用
    request Form request QueryString
    .net宏
    仿Google的一个鼠标拖动效果(转)
    保存图片时出现"800700de错误"的解决方法
    收到了csdn寄来的书
    网站可以如此复制?
    关于聚会
    GIS区域空间搜索一个必要的优化
    videobox,一个错误的名字
  • 原文地址:https://www.cnblogs.com/romaLzhih/p/11619504.html
Copyright © 2011-2022 走看看