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

贪心-区间问题——acwing

题目一:最大不相交区间数量

908. 最大不相交区间数量 - AcWing题库

分析

跟区间选点一样。区间选点:贪心——acwing-CSDN博客

代码

#include<bits/stdc++.h>
using namespace std;
 
const int N = 1e5+10;
 
struct Range {
    int l, r;
    // 重载函数
    bool operator < (const Range &W) const {
        return r < W.r;
    }
} range[N];
 
int main() {
    int n;
    cin >> n;
    for(int i = 0; i < n; i ++) {
        int l, r;
        cin >> l >> r;
        range[i] = {l,r};
    }
    // sort右端点 // range里边有重载函数定义
    sort(range, range + n);
    // 选点每次选 右端点,因为按右端点排序,可以可以尽可能覆盖多个区间,
    // 选右端点就是局部最优的体现
    int res = 0, end = -2e9;
    // 枚举区间 一一判断选点(已覆盖直接pass,没覆盖则更新,选局部最优解点)
    for(int i = 0; i < n; i ++) {
        //当前左区间 选点值
        if(range[i].l > end) {
            res ++; // 选点+1
            end = range[i].r; //更新为当前右区间
        }
    }
    cout << res << endl;
    return 0;
}

题目二:区间分组

906. 区间分组 - AcWing题库

分析

首先用一个二维数组将 区间左右端点存起来。这是数据的存储结构

对左端点排序。

贪心:

每次取所有集合中最小的右端点 与 当前区间左端点比较,如果左端点小于说明可以放入结合,也就是更新该集合的右端点。否则,多一个集合,直接入堆。

用小根堆来维护所有集合,因为贪心每次取最小,所以用小根堆维护所有结合的最右端点。

其实就是两个思考,

  1. 一是如何存储区间
  2. 二是如何解决问题

核心问题通过贪心来解决,按左端点排序

因为涉及最值,用小根堆来存储集合,维护集合。每个集合只需要存储每个集合的有端点。每次都用最小的来比较,这样可以更区间分组更密集,同时如果最小的都不行,那更大的也不行,会有交集,就需要另开集合。

代码

#include<bits/stdc++.h>
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;
}

题目三:区间覆盖

907. 区间覆盖 - AcWing题库

 

分析

考虑,区间存储结构,排序左端点,可以使用二维数组,排序右端点可以考虑结构体,加个重载<

解决核心问题:从存储的区间里挑选尽可能少的区间来覆盖一段区间。 那么首先左端点需要比该区间左端点<=才能做到覆盖。如果不行,就无解。然后还要在众多左端点比该区间左端点区间小的区间,使得该区间尽可能被覆盖多点(贪心思想体现)。即选右端点最大的,选完,待覆盖区间左端点为被选区间右端点,因为被覆盖了。重复挑选上述步骤,直至使得区间被覆盖,(能覆盖)或者区间遍历完,但仍为未覆盖。也就是无解。

综上所述:

两个边界点。第一个是待覆盖区间左端点,如果所能选区间里没有能覆盖的,(r < st) 那么无解。

第二个边界点。如果待覆盖区间被覆盖完(r>=ed)问题解决。或者,区间遍历完,仍不能使得完全被覆盖,则无解。

代码 

也可以用结构体弄个重载函数来实现区间存储和sort

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

const int N = 1e5+10;
// 二位数组存储区间
vector<vector<int>> a(N,vector<int>(2,0));

int main() {
    int st, ed;
    cin >> st >> ed;
    int n;
    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);
    
    int flag = 0, cnt = 0;
    
    for(int i = 0; i < n; i ++) {
        // 贪心:找<=要覆盖区间左端点,右端点覆盖能最大化的
        int j = i, r = -2e9;
        while(j < n && a[j][0]<=st) {
            r = max(r,a[j][1]);
            j ++;
        }
        // 覆盖不下去了,判断左边界
        if(r<st) {
            break;
        }
        // 找到一个区间覆盖一次。
        cnt ++;
        //判断 右边界
        if(r >= ed) {
            flag = 1;
            break;
        }
        //区间收缩
        st = r;
        i = j-1; // i结束循环会自增
    }
    if(flag) cout << cnt << endl;
    else cout << -1 << endl;
    
    return 0;
}


http://www.kler.cn/a/412800.html

相关文章:

  • 亮相全国集群智能与协同控制大会,卓翼飞思无人智能科研方案成焦点
  • K8S简介、使用教程
  • 基于Springboot企业级工位管理系统【附源码】
  • godot游戏引擎_瓦片集和瓦片地图介绍
  • jmeter基础06_(练习)常见的http请求
  • 蓝桥杯c++算法秒杀【6】之动态规划【下】(数字三角形、砝码称重(背包问题)、括号序列、异或三角:::非常典型的必刷例题!!!)
  • NFS搭建
  • docker里的jenkins迁移
  • 优化 Conda 下载速度:详细的代理配置和网络管理策略
  • 关于按天切割Tomcat的catalina.out日志文件的配置
  • 云技术-docker
  • 【text2sql】DB-GPT-Hub:text2sql的微调框架及基准测试套件
  • 开发常见问题及解决
  • JavaEE---计算机是如何工作的?
  • 详解Qt之QCache 高速缓存
  • 深度学习基础02_损失函数BP算法(上)
  • 分布式项目使用Redis实现数据库对象自增主键ID
  • 音视频入门基础:MPEG2-TS专题(8)——TS Header中的适配域
  • 了解UIUX设计
  • Linux 服务器使用指南:诞生与演进以及版本(一)
  • 【软考速通笔记】系统架构设计师⑤——软件工程基础知识
  • 转录组数据挖掘(生物技能树)(第11节)下游分析
  • 【设计模式】1. 构建器模式(Builder Pattern)是一种创建型设计模式
  • 林业产品推荐系统:Spring Boot设计模式
  • 【MySQL系列】使用正则表达式确保`card_secret`字段格式正确
  • 【python】面试宝典(五)