信息学奥赛一本通 1242:网线主管 | OpenJudge NOI 1.11 04:网线主管

【题目链接】

ybt 1242:网线主管
OpenJudge NOI 1.11 04:网线主管

【题目考点】

1. 二分答案

【解题思路】

看题目中的数据都带小数点,似乎这是实数域上的问题。但仔细分析,该题的输入数据精确到厘米,要求输出结果精确到厘米,实际只要在处理过程中保持为以厘米为单位,那么该问题本质上是整数域的问题。

用二分思想考虑该问题,题目问:要找最长的网线长度。对应的模板为:求满足某一条件的最大值。
网线长度需要满足的条件为:将库存中的网线按该长度进行切割,得到的网线数量大于等于居民需要的网线数量。
假设要判断为网线长度为x是否满足条件,先遍历所有库存中网线长度,每条网线长度记为l,那么l/x(整除运算)即为这条库存网线可以切出的成品网线的条数,加和求出总条数。看处理得到的网线总条数是否大于等于居民需要的网线数量k,如果是,那么满足条件,否则不满足条件。

注意单位换算,计算过程用厘米为单位,输出时转用单位米。
二分查找时,网线长度最小值设为0,最大值为 100 k m = 1 0 7 c m 100km=10^7cm 100km=107cm,考虑极端情况,假设库存中每条网线都是 1 0 7 c m 10^7cm 107cm,一共有 1 0 4 10^4 104条,而要切成 1 c m 1cm 1cm的网线,共有 1 0 7 ∗ 1 0 4 = 1 0 11 10^7*10^4=10^{11} 107104=1011条网线,超出了int的范围。所以网线计数变量要设为long long。

【题解代码】

解法1:二分答案
#include <bits/stdc++.h>
using namespace std;
int n, k, a[10005];//a[i]:第i条网线的长度 单位:厘米 
bool check(int l)//如果需要网线长度为l,最多可以得的网线段数是否大于等于k 
{
    long long ct = 0;//计数
    for(int i = 1; i <= n; ++i)
        ct += a[i] / l;//整除运算
    return ct >= k;
}
int main()
{
    double t; 
    cin >> n >> k;
    for(int i = 1; i <= n; ++i)
    {
        cin >> t;
        a[i] = round(t * 100);//单位:厘米,向下取整可能会有误差,这里使用四舍五入取整 
    }
    if(check(1) == false)//如果切成1厘米一段也不能达到要求的数量,则没有切割方案 
    {
        cout << "0.00";
        return 0;
    }  
    int l = 1, r = 1e7, m;
    while(l < r)//二分答案求满足条件的最大值
    {
        m = (l + r + 1) / 2;
        if(check(m))//如果网线长为m满足条件
            l = m;
        else
            r = m - 1;
    }
    cout << fixed << setprecision(2) << (double)l / 100;//单位转为米
    return 0;
}
  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 15
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值