“区间优化:贪心算法在区间问题中的应用“

news2024/11/25 16:55:01

1. 区间选点

给定 𝑁 个闭区间 [𝑎𝑖,𝑏𝑖],请你在数轴上选择尽量少的点,使得每个区间内至少包含一个选出的点。

输出选择的点的最小数量。

位于区间端点上的点也算作区间内。

输入格式

第一行包含整数 𝑁,表示区间数。

接下来 𝑁 行,每行包含两个整数𝑎𝑖,𝑏𝑖,表示一个区间的两个端点。

输出格式

输出一个整数,表示所需的点的最小数量。

数据范围

1≤𝑁≤105,
−109≤𝑎𝑖≤𝑏𝑖≤109

输入样例:
3
-1 1
2 4
3 5
输出样例:
2

题意解读

数轴上有一些区间,在数轴上选取几个点,要求每个区间上最少有一个点。

题解

可以使用贪心解决。

  1. 将区间按右端点排序

  2. 遍历区间,如果该区间中不包含最后选的那个点,则选取区间右端点。如果包含最后选的那个点,则跳过。

  3. 输出所选点的个数。

证明

假设最优解为 ans 个点,贪心算法求出的为 cnt 个点。 只需要证明 ans == cnt 即可。

因为 ans 是最优解,所以 ans <= cnt

贪心算法求出的结果为 cnt,每次让选取点数+1的区间一定不相交。共计cnt个这样的区间。,为了覆盖这cnt个区间, 至少需要cnt个点。所以ans >= cnt

综上: cnt == ans

代码

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int N  = 100010;
//保存区间
vector<vector<int>> a(N,vector<int>(2,0));
int n;

int main()
{
    cin >> n;
    //读入区间
    for(int i = 0; i< n; i++)
    {
        int l, r;
        cin >> l >> r;
        a[i][0] = l;
        a[i][1] = r;
    }
    // 按右端点排序
    sort(a.begin(), a.begin() + n, [](vector<int> &a, vector<int> &b){return a[1] < b[1];});
    // res 保存答案,end 是当前选的点
    int res = 0, end = -1e9 - 10;
    // 遍历区间
    for(int i = 0; i < n; i++)
    {
        // 如果当前选的点覆盖了该区间,则跳过
        if(end >= a[i][0] && end <= a[i][1]) 
            continue;
        else
        {
            // 选的点+1, 选的点更新为区间右端点
            res++;
            end = a[i][1];
        }
    }
    cout << res;
    return 0;
}

2. 最大不相交区间数量

给定 𝑁 个闭区间[𝑎𝑖,𝑏𝑖],请你在数轴上选择若干区间,使得选中的区间之间互不相交(包括端点)。

输出可选取区间的最大数量。

输入格式

第一行包含整数 𝑁,表示区间数。

接下来 𝑁 行,每行包含两个整数 𝑎𝑖,𝑏𝑖,表示一个区间的两个端点。

输出格式

输出一个整数,表示可选取区间的最大数量。

数据范围

1≤𝑁≤105,
−109≤𝑎𝑖≤𝑏𝑖≤109

输入样例:
3
-1 1
2 4
3 5
输出样例:
2

题意解读

数轴上有一些区间,选取几个区间,要求所选的区间没有重合部分,求最多能选多个区间。

题解

可以使用贪心解决。

  1. 将区间按右端点排序

  2. 遍历区间,如果该区间和上一个选的区间有重合,则跳过。如果和上一个选的区间没有重合,则选取该区间。

  3. 输出所选区间的个数。

证明

假设最优解为 ans 个区间,贪心算法求出的为 cnt 个区间。 只需要证明 ans == cnt 即可。

该贪心算法求出的结果一定是符合区间两两不相交要求的,因此 ans >= cnt

没有被选中的区间,一定是被某个选中区间pass掉的,把选中的某个区间和被该区间pass掉的所有区间看做一个集合,则共有cnt个集合。

每个集合中的区间,被pass掉的区间的右端点一定大于该集合中选中区间的右端点,因为是按照右端点排序后遍历的,所有选中区间只能pass掉右端点比他大的区间。

每个集合中的区间,被pass掉的区间的左端点一定小于该集合中选中区间的右端点,因为如果某个区间的左端点大于选中区间的右端点,则给区间一定不会被pass掉。(pass掉的条件是该区间左端点小于选中区间的右端点)

综合上面两个条件:每个集合中的区间一定两两相交。

假设ans > cnt,根据抽屉原理,一定有某个集合中被选中了1个以上的区间。又因为同一集合中的区间两两相交,因此,如果ans > cnt,则必定有区间是相交的,和题意矛盾,因此 ans 不能大于 cnt

综上:ans >= cntans 不能大于 cnt,所以ans == cnt

综上: cnt == ans

代码

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int N  = 100010;
//保存区间
vector<vector<int>> a(N,vector<int>(2,0));
int n;

int main()
{
    cin >> n;
    //读入区间
    for(int i = 0; i< n; i++)
    {
        int l, r;
        cin >> l >> r;
        a[i][0] = l;
        a[i][1] = r;
    }
    // 按右端点排序
    sort(a.begin(), a.begin() + n, [](vector<int> &a, vector<int> &b){return a[1] < b[1];});
    // res 保存答案,end 最后一个选中区间的右端点
    int res = 0, end = -1e9 - 10;
    // 遍历区间
    for(int i = 0; i < n; i++)
    {
        // 如果当前当前区间和最后一个选中区间有重合,则跳过
        if(end >= a[i][0] && end <= a[i][1]) 
            continue;
        else
        {
            // 选中区间数量+1, 更右端点
            res++;
            end = a[i][1];
        }
    }
    cout << res;
    return 0;
}

3. 区间分组

给定 𝑁 个闭区间[𝑎𝑖,𝑏𝑖],请你将这些区间分成若干组,使得每组内部的区间两两之间(包括端点)没有交集,并使得组数尽可能小。

输出最小组数。

输入格式

第一行包含整数 𝑁,表示区间数。

接下来 𝑁 行,每行包含两个整数 𝑎𝑖,𝑏𝑖,表示一个区间的两个端点。

输出格式

输出一个整数,表示最小组数。

数据范围

1≤𝑁≤105,
−109≤𝑎𝑖≤𝑏𝑖≤109

输入样例:
3
-1 1
2 4
3 5
输出样例:
2

题意解读

数轴上有一些区间,要求将区间分成若干集合,每个集合中的区间两两不重叠。问:最少需要多少个这样的集合。

解题思路

可以使用贪心算法来解决。

  1. 将区间按左端点排序。

  2. 依次遍历区间,如果当前区间能放到之前的某个集合中,则把该区间放到该集合,如果当前不能放到任意一个之前的集合中,则新开一个集合,把当前区间放到新开的集合中。

  3. 集合的数量就是答案。

关键步骤是第二步,如何判断当前区间能否放到之前的集合中。解决方法如下:

  1. 记录每个集合中保存的区间的最右侧端点,如果当前区间的左端点不和某个集合中保存的区间的最右侧端点相交,则当前区间不和该集合相交,能放到该集合中。

  2. 也就是,我们只需判断当前区间的左端点 是否和 右侧端点最小的那个集合是否相交即可。

  3. 为了快速找出右侧端点最小的那个集合,可以使用小根堆保存每个集合的右端点。

证明

设最优解为 ans, 算法解为 cnt

  1. 我们的方法找到的集合,各个集合中的区间,两两肯定不相交,因此 cnt >= ans

  2. 按照该算法,各个集合中的最后一个区间一定是两两相交的。如果存在不相交的区间,则这两个区间会被放到同一个集合中。

  3. 集合的数量,一定是当遍历到某个区间的时候,不能把当前区间放到任意一个集合中,导致了集合数量由cnt - 1 变为 cnt。也就是当前区间一定各个集合的最后一个区间有重叠部分。

  4. 综合2 3, 各个集合的最后一个区间两两相交,当前遍历到的区间和各个集合的最后一个区间都相交,因此,当前遍历的区间以及各个集合的最后一个区间两两相交。对于集合数量由cnt - 1 变为 cnt 的时候,一定有 cnt 个区间两两相交。

  5. 为了将这cnt个区间互不相交,至少需要cnt 个集合,因此 cnt <= ans

  6. 有 1 得出cnt >= ans,由 5 得出 cnt <= ans, 所以cnt == ans

代码

#include <iostream>
#include <queue>
#include <algorithm>
#include <vector>
using namespace std;
// 保存各个区间
vector<vector<int>> a(100010, vector<int>(2, 0));
int n;

int main()
{
    cin >> n;
    // 处理输入
    for(int i = 0; i < n; i++)
    {
        int l, r;
        cin >> l >> r;
        a[i][0] = l, a[i][1] = r;
    }
    //按左端点排序
    sort(a.begin(),a.begin() + n);
    //小根堆,保存所有集合的右端点,它的大小就是集合的个数
    priority_queue<int, vector<int>, greater<int>> s;
    //遍历区间
    for(int i = 0; i < n; i++)
    {
        // 当前区间不能放到现有集合中
        if(s.empty() || s.top() >= a[i][0])
        {
            // 新开一个集合,并将右端点放入
            s.push(a[i][1]);
        }
        // 当前区间能放到现有集合
        else
        {
            //更新放入集合的右端点
            s.pop();
            s.push(a[i][1]);
        }
    }
    //小根堆,保存所有集合的右端点,它的大小就是集合的个数
    cout << s.size() << endl;
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1898019.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL之备份与恢复(六)

备份与恢复 文件系统快照 先决条件和配置 创建一个快照的消耗几乎微不足道&#xff0c;但还是需要确保系统配置可以让你获取在备份瞬间的所有需要的文件的一致性副本。首先&#xff0c;确保系统满足下面这些条件。 1.所有的InnoDB文件(InnoDB的表空间文件和InnoDB的事务日志…

20.5.【C语言】求长度的两种方式

1.sizeof 用于测数据类型的长度的函数&#xff08;详细见第3篇&#xff09; 2.strlen 其计算长度时只有遇到\0才会停止&#xff0c;并且\0不会计算在内 如char arr[]{a,1,b}; printf("%d\n",strlen(arr)); 结果是个随机数&#xff01;strlen读内存中的数据&…

C++ 类和对象 构造函数

一 类的6个默认成员函数&#xff1a; 如果一个类中什么成员都没有&#xff0c;简称为空类。 例&#xff1a; #include <iostream> class Empty {// 空类&#xff0c;什么成员都没有 }; 空类中真的什么都没有吗&#xff1f;并不是&#xff0c;任何类在什么都不写时&a…

绘唐科技聚星文社是同款一键生成工具

聚星文社是同款一键生成工具 工具下载 绘唐科技成立于2015年&#xff0c;是一家专注于虚拟现实&#xff08;VR&#xff09;技术和产品开发的高科技企业。绘唐科技的目标是利用虚拟现实技术为人们带来更加沉浸式的体验&#xff0c;推动虚拟现实在各个领域的应用和发展。 绘唐科…

【博士每天一篇文献-算法】Adult neurogenesis acts as a neural regularizer

阅读时间&#xff1a;2023-12-20 1 介绍 年份&#xff1a;2022 作者&#xff1a;Lina M. Tran&#xff0c;Adam Santoro&#xff0c;谷歌DeepMind 期刊&#xff1a; Proceedings of the National Academy of Sciences 引用量&#xff1a;13 代码&#xff1a;https://github.c…

QT的编译过程(底层逻辑)

qmake -project 用于从源代码生成项目文件&#xff0c;qmake 用于从项目文件生成 Makefile&#xff0c;而 make 用于根据 Makefile 构建项目。 详细解释&#xff1a; qmake -project 这个命令用于从源代码目录生成一个初始的 Qt 项目文件&#xff08;.pro 文件&#xff09;。它…

2024年软件测试面试题大全【含答案】

一、面试基础题 简述测试流程: 1、阅读相关技术文档&#xff08;如产品PRD、UI设计、产品流程图等&#xff09;。 2、参加需求评审会议。 3、根据最终确定的需求文档编写测试计划。 4、编写测试用例&#xff08;等价类划分法、边界值分析法等&#xff09;。 5、用例评审(…

Xshll连接服务器【过程记录】

背景&目标 开学老师提供了一款服务器&#xff0c;可以网页端打开&#xff0c;但是不可进行上传文件、复制黏贴指令。 希望连接Xshll进行更有效的学习活动&#xff01; 配置过程 一、已知信息 二、配置 使用第一部分&#xff0c;先打通隧道。 【选择公钥时&#xff0c;没…

2024年【四川省安全员B证】考试及四川省安全员B证考试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年【四川省安全员B证】考试及四川省安全员B证考试题&#xff0c;包含四川省安全员B证考试答案和解析及四川省安全员B证考试题练习。安全生产模拟考试一点通结合国家四川省安全员B证考试最新大纲及四川省安全员B证…

掌握XD数字设计:打造令人惊艳的用户体验

xd是adobe旗下一款主打UI界面设计-建立原型的软件&#xff0c;它可以将wireframe、design、以及prototype等UI/UX设计流程整合到一个软件中&#xff0c;算是一款与sketch对打的软件。 与PS相比&#xff0c;在UI设计方面&#xff0c;Adobe XD有非常突出的3个优点&#xff1a;能…

【C++】哈希表 ---开散列版本的实现

你很自由 充满了无限可能 这是很棒的事 我衷心祈祷你可以相信自己 无悔地燃烧自己的人生 -- 东野圭吾 《解忧杂货店》 开散列版本的实现 1 前言2 开散列版本的实现2.1 节点设计2.2 框架搭建2.3 插入函数2.4 删除函数2.5 查找操作2.6 测试 Thanks♪(&#xff65;ω&#x…

亚信安全:《2024云安全技术发展白皮书》

标签 云计算 安全威胁 云安全技术 网络攻击 数据保护 一句话总结 《云安全技术发展白皮书》全面分析了云计算安全威胁的演进&#xff0c;探讨了云安全技术的发展历程、当前应用和未来趋势&#xff0c;强调了构建全面云安全防护体系的重要性。 摘要 云安全威胁演进&#xff…

贪吃蛇——C语言(VS2022含源代码,及源代码zip文件)

一.游戏背景 贪吃蛇是一款在世界上盛名已久的小游戏&#xff0c;贪食蛇游戏操作简单&#xff0c;可玩性比较高。这个游戏难度最大的不是蛇长得很长的时候&#xff0c;而是开始。那个时候蛇身很短&#xff0c;看上去难度不大&#xff0c;却最容易死掉&#xff0c;因为把玩一条小…

生产力工具|viso常用常见科学素材包

一、科学插图素材网站 一图胜千言&#xff0c;想要使自己的论文或重要汇报更加引人入胜&#xff1f;不妨考虑利用各类示意图和科学插图来辅助研究工作。特别是对于新手或者繁忙的科研人员而言&#xff0c;利用免费的在线科学插图素材库&#xff0c;能够极大地节省时间和精力。 …

基于CNN卷积神经网络的步态识别matlab仿真,数据库采用CASIA库

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1步态识别系统框架 4.2 CNN原理及数学表述 4.3 CASIA步态数据库 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) 1.训练过程 2.样本库 3.提取的步态能量图 4.步态识…

【YOLOv5/v7改进系列】改进池化层为ASPP

一、导言 Atrous Spatial Pyramid Pooling (ASPP)模块是一种用于多尺度特征提取的创新技术&#xff0c;旨在提升深度学习模型在语义图像分割任务中的表现。ASPP模块通过在不同的采样率下应用空洞卷积&#xff0c;可以捕获不同大小的对象以及图像的上下文信息&#xff0c;从而增…

Activity、Window、DecorView的关系

目录 一、Activity、Window、DecorView的层级关系如下图所示&#xff1a; 1、Activity 2、Window 3、DecorView 二、DecorView初始化相关源码 三、DecorView显示时机 前言&#xff1a; 不同的Android版本有差异&#xff0c;以下基于Android 11进行讲解。 一、Activi…

昇思25天学习打卡营第13天|linchenfengxue

Diffusion扩散模型 关于扩散模型&#xff08;Diffusion Models&#xff09;有很多种理解&#xff0c;本文的介绍是基于denoising diffusion probabilistic model &#xff08;DDPM&#xff09;&#xff0c;DDPM已经在&#xff08;无&#xff09;条件图像/音频/视频生成领域取得…

【ARMv8/v9 GIC 系列 5.1 -- GIC GICD_CTRL Enable 1 of N Wakeup Function】

请阅读【ARM GICv3/v4 实战学习 】 文章目录 GIC Enable 1 of N Wakeup Function基本原理工作机制配置方式应用场景小结GIC Enable 1 of N Wakeup Function 在ARM GICv3(Generic Interrupt Controller第三代)规范中,引入了一个名为"Enable 1 of N Wakeup"的功能。…

2024年【湖北省安全员-C证】考试资料及湖北省安全员-C证考试试卷

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 湖北省安全员-C证考试资料是安全生产模拟考试一点通生成的&#xff0c;湖北省安全员-C证证模拟考试题库是根据湖北省安全员-C证最新版教材汇编出湖北省安全员-C证仿真模拟考试。2024年【湖北省安全员-C证】考试资料及…