这道题是找最小值的最大化问题,那么就用二分答案
二分答案的使用条件有两个:
1.有界性(这道题的答案一定在最小绳长和最大绳长之间,满足有界性)
2.单调性(我们切的段数越多,那么这个答案就越小,所以单调递减,满足单调性)
那么我们就从0到最大绳长之间用二分法寻找答案,并依次进行check判断
如果满足条件的话l就=mid(此时的r是最小的满足条件的暂定答案)
如果不满足条件的话就r=mid(说明切的段数少于所需段数,最小值的最大值太大了,那么就缩小边界)
就这样一步步循环,最终找到最小值的最大化
其中一定要注意精度
#include<iostream>
#include<algorithm>
#include<stdio.h>
using namespace std;
const int N = 100010;
int n, m;
long long int a[N];
double ans;
bool check(double x)
{
int cnt = 0;//切的个数
for (int i = 1; i <= n; i++)//设x是这个答案,那么一共能切cnt段
{
cnt += int(a[i] / x);
}
return cnt >= m;//条件成立返回ture
}
double bsearch(double l, double r) //注意精度
{
while (r - l >= 1e-6)//r和l相等时退出循环
{
double mid = (l + r) / 2;
if (check(mid))
l = mid + 0.0005;
else
r = mid - 0.0005;
}
return l;
}
int main() {
cin >> n >> m;
double l = 0, r = 0;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
r = max(r, a[i] * 1.0);//找边界
}
printf("%.2lf", int(bsearch(l, r) * 100) / 100.0);
return 0;
}