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