备战蓝桥杯--贪心算法刷题整理3

线段和点(贪心算法)

此次题解是借鉴的,网友的题解很不错,我只不过为了大家便于理解添了几个图罢了,主要目的我是为了加深印象,在博客上存个电子笔记。如果有不对的,还望大家不吝赐教,抱拳了!
来源:https://www.cnblogs.com/fx1998/p/12726119.html

题目描述:
有n个点和m个区间,点和区间的端点全部是整数,对于点a和区间[b,c],若a>=b且a<=c,称点a满足区间[b,c]。
  求最小的点的子集,使得所有区间都被满足。
输入格式
  第一行两个整数n m
  以下n行 每行一个整数,代表点的坐标
  以下m行 每行两个整数,代表区间的范围
输出格式
  输出一行,最少的满足所有区间的点数,如无解输出-1。

  思路:
  1.首先说一下题意,当时我做这个题的时候,读题就读了好多遍才理解它所要表达的意思,就是用尽可能少的点去表示所有的区间,也就是说如果一个点被多个区间同时包含,那么这个点,就可以代表这些包含它的所有区间。
  举个例子:点为3,区间为[1,6],[2,8],[3,9], 3这个点同时在这三个区间里,这样我只要取3这个点,就可以“代表”这三个区间。换个角度来看,也就是说我们要找到它们多个区间的公共部分,这些公共部分所涉及到的区间越多越好,因为越多,所需要的点数就越少
  2.这道题巧妙之处我认为是,通过结构体对区间进行排序,比如区间为[start,end],按照end从小到大排序,end相同时,按照start从大到小排序,这样排序会使的,有多个包含关系的区间中,最里面的哪个区间在最前面。
  通过画图更形象的表达这一感觉:比如排序后的区间为:[3,3],[3,4],[2,5],[2,7],[6,9]
  在这里插入图片描述
通过图片不难看出,在不考虑[6,9]的情况下(因为与它关联的区间相对较少),剩下的这些区间中,当取这些区间的右边最小,左边最大时,不难找到最集中的区间在哪里,因此通过对结构体的排序,会使得一个点如果满足在排序后的第一个区间,就会同时满足后面的多个区间,[6,9]其实也是一样,如果他被多个区间所包围,那么只要满足它,就可以满足它后面的多个区间,这个用例只是区间太少没体现出来
  3.排序之后,就是让每一个点对应每一个区间去遍历一下,看看哪个点涉及到的区间最多,记录下区间的个数,点的个数也加一个(无需记录点是哪个,只记录有几个这样的点,依次累加,最后的点数即为所求),之后再循环并且不再考虑之前涉及到的那些区间,直到所有的区间都涉及到为止

#include <bits/stdc++.h>
using namespace std;
const int maxx = 10010;
struct node{
    int s; //start,区间的左端点
    int e; //end,区间的右端点
} p[maxx]; //区间数组

bool cmp(node n1, node n2) {
    if (n1.e != n2.e) {
        return n1.e < n2.e;
    }
    return n1.s > n2.s;
}
int a[maxx]; //存储点
int main() {
    int n, m;
    cin >> n >> m;
    for (int i = 0; i < n; i++) { //n个点
        cin >> a[i];
    }
    for (int i = 0; i < m; i++) { //m个区间
        cin >> p[i].s >> p[i].e;
    }
    
    sort(p, p+m, cmp);
    
    int k, i, j, st = 0;
    
    for (k = 0; k < n; k++) { //表示点的个数-1,因为是从0开始的
        int _max = -1;
        for (i = 0; i <= n; i++) { //遍历所有点
            for (j = st; j < m; j++) {
                if (p[j].s > a[i] || p[j].e < a[i]) {
                    break;
                }
            }
            if (j > _max) { //看这个点最多可以满足多少个区间。
                _max = j;
            }
        }
        st = _max; //下次开始的时间就在上一次点的地方开始,寻找满足的点
        if (st == m) { //所有的线段满足了,就直接退出。
            break;
        }
    }
    if (k == n) {
        cout << -1 << endl;
    } else {
        cout << k+1 << endl;
    }
    return 0;
}

再分享一个小知识,#include“sstream”文件头下的一个重要用法:数字转字符串\字符串转数字

#include"iostream"
#include"sstream"                    
using namespace std;		    
int main()
{
	stringstream ss;
	int a = 0;
	string s = "99"; // 字符型 "99"  转为  int型 99
	ss << s;
	ss >> a;  // a此时已转换为int型99 
	
	cout << a + 1;  // 输出为100
	return 0;
}



“看到你们的朴实纯真,谁还不鄙视浮躁圆滑;看到你们的高洁志趣,谁还不鄙视精致利己;看到你们对弱者的尊重,谁还不鄙视强者的骄横?”

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是刷算法备战蓝桥杯的一些建议和步骤: 1. 熟悉蓝桥杯的考试内容和题型。了解蓝桥杯的考试规则、题目类型和难度分布,可以从蓝桥杯官方网站或者相关的参考资料中获取这些信息。 2. 学习基础知识。蓝桥杯的题目通常涉及到算法和数据结构的基础知识,例如数组、链表、栈、队列、树、图、排序算法、查找算法等。建议先学习这些基础知识,掌握它们的原理和常见的应用场景。 3. 刷题练习。通过刷题来提高算法和编程能力是非常重要的。可以选择一些经典的算法题目进行练习,例如ACM/ICPC、LeetCode、牛客网等平台上的题目。刷题的过程中要注重理解题目的要求,分析问题的解决思路,编写代码实现解决方案,并进行调试和测试。 4. 参加模拟考试。蓝桥杯的模拟考试可以帮助你熟悉考试的流程和题目类型,也可以检验你的学习成果。参加模拟考试后,可以分析自己的得分情况,找出自己的不足之处,并进行针对性的复习和提高。 5. 学习优秀的解题思路和代码。在刷题的过程中,可以学习一些优秀的解题思路和代码,了解不同的解题方法和技巧。可以通过查阅相关的参考书籍、博客、论坛等获取这些信息。 6. 多做实战训练。除了刷题,还可以参加一些实战训练,例如参加ACM/ICPC比赛、编程竞赛等。这些实战训练可以提高你的编程能力和解题速度,也可以锻炼你的团队合作和应对压力的能力。 7. 多与他人交流和讨论。与他人交流和讨论可以帮助你更好地理解和掌握算法和编程知识。可以加入一些算法学习群组、论坛或者参加一些线下的学习活动,与其他学习者一起交流和分享经验。 8. 坚持练习和复习。刷算法题是一个长期的过程,需要坚持不懈地练习和复习。每天保持一定的学习时间,不断积累和提高自己的算法和编程能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Rabbit Coder

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值