首页 > 编程语言 >C++算法之旅、02 从木棒切割问题领悟二分法精髓

C++算法之旅、02 从木棒切割问题领悟二分法精髓

时间:2022-10-27 01:45:34浏览次数:81  
标签:02 right 木棒 C++ 二分法 int 长度 left

172、木棒切割问题

https://sunnywhy.com/problem/172


题目描述

给出n根木棒的长度,现在希望通过切割它们来得到至少k段长度相等的木棒(长度必须是整数),问这些长度相等的木棒的最大长度。


输入描述

第一行为两个正整数n、k(1≤n≤103、1≤k≤108),分别表示木棒的根数、需要得到的长度相等的木棒根数;

第二行为n个整数(1≤每个整数≤105),表示木棒的长度。


输出描述

一个整数,表示木棒的最大长度。如果无法达成,此时最大长度为0


思考

如果通过暴力解法,那么复杂度为\(O(n^2)\)。每轮选择一个长度遍历每根绳子。

已知木棒分割的长度为正整数,且位于\([1,max(每根绳子的长度)]\)区间。当前为有序序列。求解至少k段长度相等木棒时,木棒的最大长度。

有序序列+求第一个满足某条件的元素的位置 => 二分法


已知木棒分割的长度序列从小到大,那么每个木棒长度对应的木棒段数序列从大到小

那么求木棒的最大长度,实际上在求最后一个 >= k 的木棒段数此时的木棒长度 。


但二分法是求第一个满足某条件的元素位置,为什么呢?不妨先试着编写求最后一个满足某条件元素位置的二分法。

假定序列从小到大排列,可以很容易写出下面三种情况。但在测试过程中,往往会出现死循环或没有输出的现象。

image-20221027010854020

第1、3种情况无论如何也会让 \(left < right\) 不成立从而退出\(while\)循环。

那么很可能在第2种情况的时候陷入了死循环,求解一下死循环成立的条件。

\(\frac{left+right}{2} = left \\ \frac{right}{2} = \frac{left}{2} \\ \text 这是C语言的整除\)

二分法求解给定的\(while\)条件是\(left < right\)。显而易见,当left、right为相邻的奇偶时,且当 \(A[mid] == x\) 时,会无限死循环,每轮都会进入第2种情况。

所以牢记二分法用于寻找有序序列第一个满足某条件的元素的位置。

题解很简单,我们只需要求第一个分段数小于k的木棒长度然后减1即可。


解法

// https://sunnywhy.com/problem/172

// 考察二分查找

#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>

int countSticks(int ans[], int len, int sep) {
    int total = 0;
    for (int i = 0; i < len; i++) {
        total += ans[i] / sep;
    }
    return total;
}

int main() {
    int n, k, ans[1010], max = 0;
    // 加载数据
    scanf("%d%d", &n, &k);
    for (int i = 0; i < n; i++) {
        scanf("%d", &ans[i]);
        if (ans[i] > max) {
            max = ans[i];
        }
    }
    // 逻辑处理
    int mid, left = 1, right = max;
    while (left < right) {
        mid = (left + right) / 2;
        if (countSticks(ans, n, mid) < k) {
            right = mid;
        } else {
            left = mid + 1;
        }
    };
    printf("%d\n", --left);

    return 0;
}

二分法固定模板

image-20221027012601924

标签:02,right,木棒,C++,二分法,int,长度,left
From: https://www.cnblogs.com/linxiaoxu/p/16830697.html

相关文章

  • AcWing 1022. 宠物小精灵之收服
    宠物小精灵之收服(二维费用背包问题)原题链接:https://www.acwing.com/problem/content/1024/思路先做一个阅读理解每一个小精灵只能收一次->01背包接下来去考虑体积、......
  • CSP-S2022 游寄
    前言:最后确实寄了,因为疫情,都没考成。\(8.26\)占坑。\(8.23\)参加浴谷月赛初赛模拟,报的\(S\)组,只有\(71\)分。\(8.25\)\(AK\)了同学出的比赛。\(8.26\)参加了......
  • P5377 鸽鸽的分割 评论及c++题解
    P5377鸽鸽的分割1.原题连接2.评论下位红(划掉简单题只需要推导出公式或分类讨论就行了这里只给出公式解法根据题意在一个圆上确定n(n∈正整数)个点,求最多可被......
  • C++函数指针和回调函数
    C++函数指针和回调函数在C++中函数指针名就是函数的地址//定义函数指针:返回类型(*pfunc)(形参列表)void(*pfunc)(int,string);int(*pfunc)(int,string,double);......
  • C++ 面向对象高级开发(四) Sting类 浅谈
    StringClass 带指针的Class不能用默认拷贝  构造函数、拷贝构造、拷贝赋值、析构函数   浅拷贝导致内存泄漏两个指针指一个  深拷贝  ......
  • CSP 2022 退役寄
    坐标SC。去年J组不错,不打了。本来说考完初赛晚上就开坑的,结果没来得及,拖到复赛前夕...9.10初赛线上了,本来希望延迟的,虽然很不现实。。。其实线上线下都一样,虽然还是......
  • C++ 面向对象高级开发 (五) 栈堆、new和delete
                   ......
  • 【leetcode_C++_栈与队列_day9】232.用栈实现队列&&225. 用队列实现栈
    知识补充:栈与队列理论基础(C++)C++中stack是容器么?​ stack:堆栈栈是以底层容器完成其所有的工作,对外提供统一的接口,底层容器是可插拔的(也就是说我们可以控制使用哪种......
  • C++标准库字符串流sstream
    sstream与strstream在C++有两种字符串流,一种在<strstream>中定义,另一种在<sstream>中定义,两者的区别如下:strstream里包含strstreambuf、istrstream、ostrstream、strst......
  • 模板整理(2022.10)
    模板整理(2022.10)1.线性筛素数boolis_prime[100000005];//是否为素数intprime[100005],cnt;//素数数组,cnt:素数个数voidget_prime(intmaxn){ memset(is_prime,1......