割竹子
问题描述
有N根竹子,第i根长为Li,现需要m根等长竹子。你可以对n根竹子进行任意分割(不能拼接),计算出这m根竹子最长的长度多少?
输入描述:
第一行包括两个整数N,M,含义如题所述(1 <= N,M <= 100000)
第二行包含N个整数,分别对应N根竹子的长度(0 < l[i] < 10^9)
输出描述:
一个数字,表示分割后最长的长度,保留两位小数
思路解析
本题采用二分法,类似于数据结构中的二分查找法
取最长的一半进行判断,少了则取1/4,多了则取3/4
代码如下
public class test6 {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int N = sc.nextInt();
int M = sc.nextInt();
int arr[]=new int[N];
for (int i = 0; i < arr.length; i++) {
arr[i]=sc.nextInt();
}
double c=arr[0];
double a=0;
double b = 0 ;
//找出最长的竹子
for (int i = 0; i < arr.length; i++) {
if (c<arr[i]) {
c=arr[i];
}
}
//二分法
while (c-a>1E-6) {
int count=0;
b=(c+a)/2;
if (check(arr,b)<M) {
c=b;
}else {
a=b;
}
}
int f=8;
double x;
//保留后两位
x=((double)((int)(b*100)))/100;
System.out.println(String.format("%.2f",x));
}
//当前长度可以取得的竹子段数
public static int check(int [] arr,double a) {
int count=0;
int b;
for (int i = 0; i < arr.length; i++) {
b=(int) (arr[i]/a);
count+=b;
}
return count;
}
}
但此方法仍存在漏洞,例如输入 3 3 2 3 7这组数据,得到的结果为2.99而不是3.00
因为此时二分法无法取到极限值,只能无限接近于该值