Cable master (POJ No. 1064)

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

限制条件:

1≤N≤10000

1≤K≤10000

1≤Li≤100000

输入:

N = 4

K = 11

L = {8.02,7.43,4.57,5.39}

输出

2.00(每条绳子分别可以得到4条、3条、2条、2条,共计11条绳子)


import java.util.Scanner;

public class Main {
    public static int N, K;
    public static double[] L = new double[100001];
    public static void main(String[] args) {
       Scanner cin = new Scanner(System.in);
       N = cin.nextInt();
       K = cin.nextInt();
       for (int i = 0; i < N; ++i) {
           L[i] = cin.nextDouble();
       }
       cin.close();
       solve();
    }
    public static void solve() {
        double lo = 0, hi = 100001; // 区间初始化的时候,只要使用足够大的数字INF,这里大于最长的绳子长度就可以,
        // 当然也可以Double.MAX_VALUE,64位,2的63次方,100次循环完全足够把精度确定到范围内)
        for (int i = 0; i < 100; ++i) {
            double mid = lo + ((hi - lo) >> 1);
            if (C(mid)) lo = mid; // 如果满足条件num>=K,说明切的绳子比较多,可以每一段再长一点,区间左端右移
            else hi = mid; // 如果不满足,说明每根绳子切的太长,不满足切出K条长度一样的绳子,区间右端左移
        }
        // 循环100次,精度有10的-31精度范围
        System.out.printf("%.2f", (Math.floor(hi * 100)) / 100);
    }
    public static boolean C(double x) {
        int num = 0;
        for (int i = 0; i < N; ++i) {
            num += (int)(L[i] / x);
        }
        return num >= K;
    }
}

这里for(int i= 0; i < 100;++i)也可以改成while(hi-lo>eps)这样的,但是如果eps太小了,就有可能因为浮点小数精度的原因导致陷入死循环。

在求解最大化或最小化的问题中,能够比较简单的判断条件是否满足,那么使用二分搜索可以很好的解决问题


========================================Talk is cheap, show me the code=======================================