当前位置: 首页 > news >正文

NO.63十六届蓝桥杯备战|基础算法-⼆分答案|木材加工|砍树|跳石头(C++)

⼆分答案可以处理⼤部分「最⼤值最⼩」以及「最⼩值最⼤」的问题。如果「解空间」在从⼩到⼤的「变化」过程中,「判断」答案的结果出现「⼆段性」,此时我们就可以「⼆分」这个「解空间」,通过「判断」,找出最优解。
这个「⼆分答案」的原理其实很容易理解,重点是如何去「判断」答案的可⾏性。

P2440 木材加工 - 洛谷

设要切成的⻓度为x ,能切成的段数为c 。根据题意,我们可以发现如下性质:

  • 当x 增⼤的时候,c 在减⼩。也就是最终要切成的⻓度越⼤,能切的段数越少;
  • 当x 减⼩的时候,c 在增⼤。也就是最终要切成的⻓度越⼩,能切的段数越多。
    那么在整个「解空间」⾥⾯,设最终的结果是ret ,于是有:
  • 当x<=ret时,c>=k。也就是「要切的⻓度」⼩于等于「最优⻓度」的时候,最终切出来的段
    数「⼤于等于」k ;
  • 当x > ret时,c < k 。也就是「要切的⻓度」⼤于「最优⻓度」的时候,最终切出来的段数
    「⼩于」k;
    在解空间中,根据ret的位置,可以将解集分成两部分,具有「⼆段性」,那么我们就可以「⼆分答案」。
    当我们每次⼆分⼀个切成的⻓度x 的时候,如何算出能切的段数c ?
  • 很简单,遍历整个数组,针对每⼀根⽊头,能切成的段数就是a[i] / x
    ![[Pasted image 20250403162611.png]]
calc(mid) >= k  ->  left = mid;
calc(mid) < k   ->  right = mid - 1;

有-1,mid = (left + right + 1) / 2
x表示切割出来的小段的长度
c表示在x的基础下,最多能切出多少段
k表示最终要切割的段数
calc计算切割长度为x的时候,能切出来多少段

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 1e5 + 10;
LL n, k;
LL a[N];

LL calc(LL x)
{
    LL cnt = 0;
    for (int i = 1; i <= n; i++)
    {
        cnt += a[i] / x;        
    }
    return cnt;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);

    cin >> n >> k;
    for (int i = 1; i <= n; i++) cin >> a[i];

    LL left = 0, right = 1e8;
    while (left < right)
    {
        LL mid = (left + right + 1) / 2;
        if (calc(mid) >= k) left = mid;
        else right = mid - 1;
    }
    cout << left << endl;
    
    return 0;
}
P1873 [COCI 2011/2012 #5] EKO / 砍树 - 洛谷

设伐⽊机的⾼度为H ,能得到的⽊材为C 。根据题意,我们可以发现如下性质:

  • 当H 增⼤的时候,C 在减⼩;
  • 当H 减⼩的时候,C 在增⼤。
    那么在整个「解空间」⾥⾯,设最终的结果是ret ,于是有:
  • 当H<=ret时,C>=M。也就是「伐⽊机的⾼度」⼤于等于「最优⾼度」时,能得到的⽊材
    「⼩于等于」M;
  • 当H>ret时,C<M。也就是「伐⽊机的⾼度」⼩于「最优⾼度」时,能得到的⽊材「⼤
    于」M。
    在解空间中,根据ret的位置,可以将解集分成两部分,具有「⼆段性」,那么我们就可以「⼆分答案」。
    当我们每次⼆分⼀个伐⽊机的⾼度H 的时候,如何算出得到的⽊材C ?
  • 很简单,遍历整个数组,针对每⼀根⽊头,能切成的⽊材就是a[i] - H
    ![[Pasted image 20250403165351.png]]
calc(mid) >= M  ->  left = mid;
calc(mid) < M   ->  right = mid - 1;

有-1,mid = (left + right + 1) / 2
h表示伐木机的高度
c表示在h的基础下,所能获得的木材
calc计算高度为h的时候,所能获得的木材

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
const int N = 1e6 + 10;
LL n, m;
LL a[N];

LL calc(LL x)
{
    LL ret = 0;
    for (int i = 1; i <= n; i++)
    {
        if (a[i] > x) ret += a[i] - x;        
    }
    return ret;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);

    cin >> n >> m;
    for (int i = 1; i <= n; i++) cin >> a[i];

    LL left = 1, right = 2e9;
    while (left < right)
    {
        LL mid = (left + right + 1) / 2;
        if (calc(mid) >= m) left = mid;
        else right = mid - 1;
    }
    cout << left << endl;
    
    return 0;
}
P2678 [NOIP 2015 提高组] 跳石头 - 洛谷

设每次跳的最短距离是x ,移⾛的⽯头块数为c 。根据题意,我们可以发现如下性质:

  • 当x 增⼤的时候,c 也在增⼤;
  • 当x 减⼩的时候,c 也在减⼩。
    那么在整个「解空间」⾥⾯,设最终的结果是ret ,于是有:
  • 当x<=ret时,c<=M。也就是「每次跳的最短距离」⼩于等于「最优距离」时,移⾛的⽯头块数「⼩于等于」M;
  • 当x>ret时,c>M。也就是「每次跳的最短距离」⼤于「最优距离」时,移⾛的⽯头块数「⼤于」M。
    在解空间中,根据ret的位置,可以将解集分成两部分,具有「⼆段性」,那么我们就可以「⼆分答案」。
    当我们每次⼆分⼀个最短距离x 时,如何算出移⾛的⽯头块数c ?
  • 定义前后两个指针i, j 遍历整个数组,设i ≤ j ,每次j 从i 的位置开始向后移动;
  • 当第⼀次发现a[j] - a[i] ≥ x 时,说明[i + 1, j - 1] 之间的⽯头都可以移⾛;
  • 然后将i 更新到j 的位置,继续重复上⾯两步。
    ![[Pasted image 20250403193116.png]]
calc(mid) <= M  ->  left = mid;
calc(mid) > M   ->  right = mid - 1;

有-1,mid = (left + right + 1) / 2
x表示最短跳跃高度
c表示在x的基础下,移走岩石的数目

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
const int N = 5e4 + 10;
LL l, n, m;
LL a[N];

LL calc(LL x)
{
    LL ret = 0;
    for (int i = 0; i <= n; i++)
    {
        int j = i+1;
        while (j <= n && a[j] - a[i] < x) j++;
        ret += j - i - 1;
        i = j-1;
    }
    return ret;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);

    cin >> l >> n >> m;
    for (int i = 1; i <= n; i++) cin >> a[i];
    a[n + 1] = l;
    n++;
    LL left = 1, right = l;
    while (left < right)
    {
        LL mid = (left + right + 1) / 2;
        if (calc(mid) <= m) left = mid;
        else right = mid - 1;
    }
    cout << left << endl;
    
    return 0;
}
http://www.dtcms.com/a/109997.html

相关文章:

  • ZCC8702,LED驱动芯片的“六边形战士”可替代SY8707
  • 服务器有2张显卡,在别的虚拟环境部署运行了Xinference,然后又建个虚拟环境再部署一个可以吗?
  • ngx_time_init
  • EIR管理中IMEI和IMSI信息的作用
  • 【AI赋能:58招聘数据的深度剖析之旅】
  • NHANES指标推荐:BRI
  • 基于大模型的主动脉瓣病变预测及治疗方案研究报告
  • 《系统分析师-基础篇-1-6章总结》
  • 非对称加密:原理、算法与应用全解析
  • 工具介绍 | SafeLLMDeploy教程来了 保护本地LLM安全部署
  • 2025高频面试设计模型总结篇
  • 采用离散频率索引k和模拟频率f生成信号(MATLAB)
  • Spring Boot 集成 Redis中@Cacheable 和 @CachePut 的详细对比,涵盖功能、执行流程、适用场景、参数配置及代码示例
  • [C语言入门] 结构体
  • RNN万能逼近定理证明
  • 《2024年全球DDoS攻击态势分析》
  • 2025年内外网文件交换系统排名分析
  • 【3.软件工程】3.5 V开发模型
  • 深度学习与神经网络 | 邱锡鹏 | 第二章学习笔记
  • 微服务。1 微服务
  • Java学习总结-IO流
  • 如何免费制作办事指南二维码
  • 如何进行风电场微观选址
  • 如何在Windows上找到Python安装路径?两种方法快速定位
  • 深度学习deeplearn3
  • 基于飞桨框架3.0本地DeepSeek-R1蒸馏版部署实战
  • 质检LIMS系统在环境监测站的应用 环境监测场景下的LIMS系统应用
  • thinkphp每条一级栏目中可自定义添加多条二级栏目,每条二级栏目包含多个字段信息
  • 连接与效率的艺术:解码ToB 移动端协同产品的用户体验设计奥秘
  • PyTorch优化器