POJ 1064 Cable master [二分查找] 《挑战程序设计竞赛》3.1

题目链接 POJ 1064 Cable master
题目大意:

给你n根长度分别为 Li 的绳子。要从它们中切割出k条长度相同的绳子,问这k根绳子能切割的最大长度是多少。答案保留两位小数。

Input

第一行 n, k
接下来n行,每行一个2位小数的浮点数,表示 Li

Output

最大能切割的长度

Sample Input

4 11
8.02
7.43
4.57
5.39

Sample Output

2.00

题解:

二分范围为0到n条绳子中的最大长度。设cut(mid) 为每次二分计算出的剪得长度相同的绳子的条数, 我们要找的是 cut(mid) >= k 的最大的mid
在二分搜索时,要设置合理的结束条件来满足精度要求。1次循环可以把区间范围缩小一半, 100次循环就可以达到 1030 的精度范围,基本上是没问题了。除此之外,也可以把终止条件设为 (rl)>EPS ,指定一个区间大小。在这种情况下,如果EPS取得太小了,就有可能会因为浮点小数精度的原因导致陷入死循环,要小心。

自以为对二分法比较熟练,但没想到WA了这么多次。。
由于是对浮点数二分,和整数的处理还是略有不同的
直接用printf(“%.2lf”, r) ,会自动帮你四舍五入。死舍没问题,五入就错了。
所以输出的时候特殊处理了一下。

代码:

#include <iostream>
#include <cstdio>
#define MAXN 10010
using namespace std;

int n, k;
double a[MAXN], M = 0.0;

int cut(double m) {
    int cnt = 0;
    for (int i = 0; i < n; i++) {
        cnt += (int)(a[i]/m);
    }
    return cnt;
}

//二分
void solve() {
    double l = 0.0, r = M;
    for (int i = 0; i < 200; i++) {
        double mid = 1.0*(l+r)/2;
        if (cut(mid) >= k) l = mid;
        else r = mid;
    }

   r *= 100;
   int t = (int)r;
   // t/100为整数部分, t%100为小数部分,长度不足2要补0
   printf("%d.%02d\n", t/100, t%100);
}

int main() {
    scanf("%d%d", &n, &k);
    for (int i = 0; i < n; i++) {
        scanf("%lf", &a[i]);
        M = max(M, a[i]);
    }

    solve();

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值