二分搜索
二分搜索的一种应用:求最大(最小值),可以建立一个检验函数,用x代表其中的值,返回解是否可行的boolean,然后在主函数中用左边界表示一定成立的解,右侧表示一定不可能的解,不断把中值代入方程检验,缩小范围,直到得出近似解。
1.n根绳子能剪出k根最长多长的绳子。
2.求牛舍给定情况下,两头牛之间的最大距离。
3.求物品的最大平均价值。(wi,vi已知)
主函数:
public double solve(int n,int k,double[] ripes){
double left = 0,right = Double.MAX_VALUE;
for(int i=0;i<100;i++){
//控制精度
double mid = (left+right)/2;
if(C(mid,ripes,k)){
left = mid;//left是一定可行的解
}else{
right = mid;//right是一定不行的
}
}
return Math.floor(left*100)/100;
}
public int solve(int num_of_cows,int[] house){
Arrays.sort(house);
System.out.println(Arrays.toString(house));
int left = 0,right = Integer.MAX_VALUE;
while(left+1 < right){
int mid = (left+right)/2;
if(C(num_of_cows,house,mid)){
left = mid;
}else{
right = mid;
}
}
return left;
}
public double solve(int num,int k,int[][] relation){
double left = 0,right = 10000;
for(int i=0;i<100;i++){
double mid = (left+right)/2;
if(C(num,k,relation,mid)){
left = mid;
}else{
right = mid;
}
}
return left;
}
求值函数:
public boolean C(double x,double[] ripes,int k){
int num = 0;
for(int i=0;i<ripes.length;i++){
num+=(int)ripes[i]/x;
}
return num >= k;
}
public boolean C(int num,int k,int[][] relation,double ax){
double[] y = new double[relation.length];
for(int i=0;i<y.length;i++){
y[i] = relation[i][1] - ax*relation[i][0];
}
Arrays.sort(y);
System.out.println(Arrays.toString(y));
double sum = 0;
for(int i=0;i<k;i++){
sum+=y[num-i-1];
}
return sum >= 0;
}
public boolean C(int num_of_cows,int[] house,int dx){
int last = 0;
for(int i=1;i<num_of_cows;i++){//每头牛找位子
int cur = last+1;
while(cur < house.length && house[cur] - house[last] < dx){
cur++;
// System.out.println(cur+",");
}
if(cur == house.length){//牛还有,屋子不够了
return false;
}
last = cur;
}
return true;
}