欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

poj 1064 二分查找变形—判定并找到可行解

程序员文章站 2024-03-20 17:23:58
...

题目来源: poj 1064 Cable master

题目概述:有N条绳子,他们的长度分别为Li,如果从它们中切割出k条长度相同的绳子的话,这K条绳子每条能有多长?


思路:使用二分法,判断最大值的范围,有三种情况:

  • 当前剪的总数 小于 题目要求的K条,这时候我们确定,当前的区间范围来说,右边界过大,导致中间值middle过大,所以要将右边界=middle_value。
  • 当前剪的总数相等题目要求的k条,这时候我们确定,当前的区间范围来说,middle正处于合适的范围区间,但是middle的取值是不是最大值呢,需要middle的数值扩大,所以将左边界扩大,左边界 = middle_value.
  • 当前剪得的总数大于题目要求的k条,这时候我们确定,当前区间范围来说,middle的取值满足要求,但是是否是最大值,还是需要重新确认边界,所以左边界=middle,在此扩大middle的取值

注意:因为此时左边界(left_value),右边界(right_value),中间值(middle_value)都是浮点数,所以判断区间的时候会有两种方法:

  • 左边界 - 右边界 > 一个足够小的数值,一般都设置为1e-5
  • 一种是循环到合适的数值,一般来说,循环一百次,相当于达到了10的-30次方的精度,也是足够的


#include<iostream>
#include<stdio.h>
#include<math.h>
#define INF 9999999;
using namespace std;

bool pd_section (double middle, double* dataSet, int K, int N){
    int num = 0;
    for (int i=0; i<N; i++){
        num += (int)(dataSet[i] / middle);
    }
    bool result = num >= K ? true : false;
    return result;
}

int main () {
    int N,K;
    double dataSet[10001];
    while (cin>>N>>K){
        for (int i=0; i<N; i++){
            cin>>dataSet[i];
        }
        double start_flag, end_flag;
        start_flag = 0;
        end_flag = INF;
        for (int i=0; i<=100; i++){
            double middle_flag = (start_flag + end_flag) / 2;
            if ( pd_section(middle_flag, dataSet, K, N)){
                start_flag = middle_flag;
            } else {
                end_flag = middle_flag;
            }
        }
        printf("%.2lf\n", floor(end_flag * 100) / 100);
    }
    return 0;
}
相关标签: 二分查找 poj