题意:有N条绳子,长度分别为Li,从中切割出k条长度相同的绳子,这K条绳子最长能有多长?保留两位小数(直接截取2位)。
输入
4 11
8.02 7.43 4.57 5.39
输出
2.00
算法:二分搜索法
//二分搜索法
//#include<bits/stdc++.h>
#include<stdio.h>
#include<math.h>
//using namespace std;
int n,k;
double a[10005];
int inf=999999999;
bool C(double x)//有多少个长度为x的绳子
{
int num=0;
for(int i=1;i<=n;i++){
num+=(int) (a[i]/x);
}
return num>=k;//当前x符合条件
}
void search()
{
double mid,lb,ub;//初始化范围
lb=0;ub=inf;
for(int i=0;i<100;i++){//控制精度 可以达到10^-30
mid=(lb+ub)/2.0;
if(C(mid)) lb=mid;//太小了,还可以大点
else ub=mid;
}
//printf("%.2f\n",ub);//会四舍五入 WA
printf("%.2lf\n",floor(ub*100)/100);//保留两位小数,ub表示最大符合 AC
}
int main(void)
{
scanf("%d %d",&n,&k);
for(int i=1;i<=n;i++)
scanf("%lf",&a[i]);
//float %f double %lf
search();
return 0;
}
/*
4 11
8.02 7.43 4.57 5.39
*/
//分割线----------------------------------------------
/*
#include<bits/stdc++.h>
using namespace std;
int main(void)
{
double a,b,c;
a=1.23567;
b=1.23567;
c=1.23567;
printf("a:%%.2f: %.2lf\n",a);//会四舍五入
printf("b:floor(a*100)/100: %.2lf\n",floor(a*100)/100);//直接保留2位,不会四舍五入
printf("floor: %.2lf\n",floor(c));//向下取整,返回double
return 0;
}
*/
总结:
什么时候我们可以用到二分搜索呢?
1.在求解最大化或者最小化的问题
2.能简单判断条件是(如上面的C函数)否满足:求满足条件C(x)的最小x,若有“所有大于x的自变量d也都满足C(d)”
3.有序
则可以使用二分算法来解决。
我觉得有很多人包括我,对于本题的精度有点疑惑,在上面代码有详细解释。不过经过本人测试,本题答案要点不是我们所理解的保留两位小数第三位四舍五入,而是直接截取两位小数,不需要四舍五入。