908与905的代码完全一样 思路相似不做额外篇幅
题目
给定 N个闭区间 [ai,bi],请你在数轴上选择尽量少的点,使得每个区间内至少包含一个选出的点。
输出选择的点的最小数量。
位于区间端点上的点也算作区间内。
输入格式
第一行包含整数 N,表示区间数。接下来 N行,每行包含两个整数 ai,bi,表示一个区间的两个端点。
输出格式
输出一个整数,表示所需的点的最小数量。
思路分析
1.结论:将每个区间按照右端点从小到大进行排序,从前往后枚举区间,end值初始化为无穷小
如果本次区间不能覆盖掉上次区间的右端点, ed < range[i].l
说明需要选择一个新的点, res ++ ; ed = range[i].r;
2.证明:由贪心策略可知,贪心方法将会选择尽量少的点覆盖所有的区间,且每个点对应的区间的集合不相交;使用反证法,不妨假设ans<cnt成立,由于ans是最优解,那么ans个点也覆盖所有的区间,即存在更少的点ans可以覆盖所有的区间。这与贪心策略不符,因为一旦有更少的点可以覆盖所有的区间,那么它一定是贪心解cnt,否则更少的点不能覆盖所有的区间,与假设矛盾。因此ans≥cnt成立。
3.人话:和leetcode中的穿针引线一样,是一种判断区间的问题。
利用vector存储区间代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef pair<int,int> PII;
vector<PII> range;
int n;
bool cmp(PII x,PII y)
{
return x.second < y.second;
}
int main()
{
cin >> n;
while(n--)
{
PII p;
cin >> p.first >> p.second;
range.push_back(p);
}
sort(range.begin(),range.end(),cmp);
int res = 1;
for(int i = 1,j = 0;i < range.size();i++)
{
if(range[i].first > range[j].second)
{
res++;
j = i;
}
}
cout << res << endl;
return 0;
}
acwing基础课yxc版本
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int n;
//利用结构体存储区间————知识点1
struct Range
{
int l, r;
//重载<号
//第一个const:const& 表示常引用,防止在函数内部对参数值的修改,以确保函数不会意外改变传入的对象。
//第二个const:用于修饰函数本身,表示成员函数是一个常量成员函数。这意味着该成员函数在内部不会修改成员变量的值。常量成员函数可以在常对象中调用,但不能修改对象的状态。
bool operator< (const Range &W)const
{
return r < W.r;
}
}range[N]; //创建结构体的同时直接开辟结构体数组
int main()
{
scanf("%d", &n);
for (int i = 0; i < n; i ++ ) scanf("%d%d", &range[i].l, &range[i].r);
//结构体内部已经编译了sort规则,这里sort不用写第三个参数
sort(range, range + n);
//最开始需要与最小值比较一次所以res定义为0而不是1
int res = 0, ed = -2e9; //最开始定义一个无穷小的ed
for (int i = 0; i < n; i ++ )
if (ed < range[i].l)
{
res ++ ;
ed = range[i].r;
}
printf("%d\n", res);
return 0;
}