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=======================================