先审题,要求每条绳子最小长度的最大值,所以我们使用二分法。
因为题目中说了输入输出都是小数,我们可以用double,但是这样会出现其他的问题(比如在二分时精度无法保证),这里只是两位小数,所以我们可以直接用整型存下来,最后除以100。
再来看思路:已知要割的绳子的段数和每条绳子的长度,那么我们可以转变一下思路,取一个最大值和一个最小值,再以1的长度来遍历,但这样会爆,所以自然想到二分------->取一个很大很大的值(一定不要取数组里的最大值,血的教训!!!)再不断的取中间值 ,每次取到一个中间值我们就用它来和每段绳子的长度作除法,看看最后取到的绳子有多少。这样就得到最终答案啦!
上代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e4 + 10;
int len[N];
int n, k;
bool check(int x)//判断我们取的那个中间值能截到多少绳子
{
int cnt = 0;
for (int i = 1; i <= n; ++i)
{
cnt += len[i] / x;
}
return cnt >= k;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n >> k;
for (int i = 1; i <= n; ++i)
{
double a;
cin >> a;
len[i] = a * 100;//取整
}
int l = 0, r = 1e9;//找一个非常大的端点
double ans = 0;
int mid;
while (l <= r)//开始二分
{
mid = (l + r) >> 1;
if (mid == 0)break;//这里必须要有一个判0点,因为是整数所以可能除的时候会变成0,导致RE
if (check(mid))//中间值比k小
{
ans = mid;
l = mid + 1;//向右区间移动
}
else
r = mid - 1;//小了,向左区间移动
}
printf("%.2f", ans / 100.);//一定要用printf!!!下面的cout会导致一个答案小了0.01!!!
//cout << fixed << setprecision(2) << ans/100.0 << endl;
return 0;
}