枚举算法实践2-切割木棍 c++

题目描述

我们有n根的木棍。现在从这些木棍中切割出来m条长度相同的木棍,问这m根木棍最长有多长?

输入数据

  • 第一行输入两个数字,n和m n(1<=n<=1000)为木棍数目 m(1<=m<=1000)为需要切割出的相同长度的木棍数目
  • 随后n个正整数,表示原始木棍的长度(<=10000)

输出数据

每组输出一行结果,表示切割后绳子的最长长度(保留两位小数)

样例输入

4 5
5 6 7 8

样例输出

4.00

初始思路

  • 因为要求切割的最大长度,本来想着从木棍长度中找到最大的长度,不断递减向下寻找,直到能切割的数目>= m。!不过不可以,因为切割的长度极有可能不为整数。

正解思路

  • 明确切割木棍的长度最粗略的范围就是0到当前木棍中最长的那个
  • 明确范围之后,我们就可以使用二分查找了(因为数据是有序的)
  • 每一次查找要计算 以当前mid指向的长度 切割的 木棍数目num
  • num 大于等于m(想要的数目) 说明木棍长度小了 所以要更新leftmid
  • 反之 更新 rightmid
  • 直到left 等于right时,就找到了满足当前条件的最长的切割长度了

代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cmath> //round四舍五入
using namespace std;
int main()
{
    int n, m;
    vector<int> lens;
    cin >> n >> m;
    for (int i = 0; i < n; i++)
    {
        int temp;
        cin >> temp;
        lens.push_back(temp);
    }
    auto max = max_element(lens.begin(), lens.end()); //max_element 返回的是迭代器
    double l = 0, r = *max;                           //能切割的木棒长度 最粗略的范围就是0到当前木棒中最大的
    double mid;
    while (l + 0.01 < r) //不断更新范围 直到 l = r = 最佳解
    {
        int num = 0;
        mid = round(((l + r) / 2.00) * 100) / 100.00; //保证精度
        // float middd = round(l + r) / 2.00;            //不可以 (4+4.5)=4.5
        for (int i = 0; i < n; i++)
            num += (int)(lens[i] / mid); //针对当前长度 看每个lens能切割成多少个
        if (num >= m)                    //当前的切割 得到的木棍多 说明当前的切割长度小了
            l = mid;
        else
            r = mid;
    }
    printf("%.2f", l);
    system("pause");
    return 0;
}

补充

  • mid = round(((l + r) / 2.00) * 100) / 100.00; 为了保证精度到小数点后两位
  • num += (int)(lens[i] / mid); 因为木棍切割只能向下取整,所以int的除法刚好合适
  • max_element() 返回容器中最大值的迭代器,所以输出值的话要对其取 *
  • 对于格式化的输入和输出,scanfprintf更方便
  • 若文章存在问题,还请各位大佬批评指正,共同进步。
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值