680. 剪绳子
有N根绳子,第i根绳子长度为LiLi,现在需要M根等长的绳子,你可以对N根绳子进行任意裁剪(不能拼接),请你帮忙计算出这M根绳子最长的长度是多少。
输入格式
第一行包含2个正整数N、M,表示原始绳子的数量和需求绳子的数量。
第二行包含N个整数,其中第 i 个整数LiLi表示第 i 根绳子的长度。
输出格式
输出一个数字,表示裁剪后最长的长度,保留两位小数。
数据范围
1≤N,M≤1000001≤N,M≤100000,
0<Li<1090<Li<109
输入样例:
3 4
3 5 4
输出样例:
2.50
样例解释:
第一根和第三根分别裁剪出一根2.50长度的绳子,第二根剪成2根2.50长度的绳子,刚好4根。
题解:
#include <bits/stdc++.h> #define N 100100 using namespace std; int n,m; int a[N]; bool check(double mid){ int cnt=0; for(int i=0;i<n;i++) { cnt+=a[i]/mid; } return cnt>=m; } int main(){ cin >> n >> m; for(int i=0;i<n;i++) { cin >> a[i]; } double r=0,l=1e9; while(l-r>=1e-4) { double mid=(l+r)/2; if(check(mid)) { r=mid; } else{ l=mid; } } printf("%.2f\n",r); system("pause"); }
思考:
浮点数二分相比于整数二分,不用考虑边界问题,较为简单。二分法的核心思想在于逐步缩小并确定数的范围,进而根据精度求出相应的数。本题,直接进行最优化求解难以求出,但通过转换思路,用二分法确定出所求的绳子长度并进行判断是容易做到的。因此,我们先确定绳子取值的边界,然后通过---取mid---判断该mid所对应的m值与要求的m值的大小关系---如果m'>=m,则取二分右部区间,左端点变为mid---如果m'<=m,则取二分左部区间,右端点变为mid。遍历判断,直到找到符合精度要求的值为止。
浙公网安备 33010602011771号