刷题集(13)
#T1324. 【例6.6】整数区间
题目描述
请编程完成以下任务:
1.从文件中读取闭区间的个数及它们的描述;
2.找到一个含元素个数最少的集合,使得对于每一个区间,都至少有一个整数属于该集合,输出该集合的元素个数。
输入
首行包括区间的数目n,1≤n≤10000,接下来的n行,每行包括两个整数a,b,被一空格隔开,0≤a≤b≤10000,它们是某一个区间的开始值和结束值。
输出
第一行集合元素的个数,对于每一个区间都至少有一个整数属于该区间,且集合所包含元素数目最少。
样例
输入数据 1
4
3 6
2 4
0 2
4 7输出数据 1
2来源
一本通在线评测
问题分析
给定n个闭区间[a_i, b_i],需要选择一些整数点,使得每个区间至少包含一个点。
目标是选择点的数量最小化。
贪心算法思路
排序区间:首先将所有区间按照结束值b_i从小到大排序。如果结束值相同,可以按开始值a_i排序(但本题中结束值相同不影响核心逻辑)。
初始化:设置一个变量
current_point表示当前选择的点(初始值可设为-1),并初始化点数计数count = 0。遍历区间:对于每个排序后的区间:
如果当前区间的开始值a_i大于
current_point,说明当前点无法覆盖该区间,需要新选一个点。此时选择该区间的结束值b_i作为新点(因为选择结束点可以尽可能覆盖后续区间),并更新current_point = b_i,同时count加1。否则,当前点已经覆盖该区间,无需操作。
输出结果:最终
count即为所需最小集合的元素个数。
算法正确性证明
贪心策略选择结束值最小的区间点,可以保证该点覆盖所有以该点结束的区间,同时为后续区间留下更多空间。
数学上可以证明,这种策略能得到全局最优解。
复杂度分析
排序区间的时间复杂度为O(n log n)。
遍历区间的时间复杂度为O(n)。
总复杂度为O(n log n),适用于n≤10000的规模。
示例验证
对于样例输入:
4
3 6
2 4
0 2
4 7排序后(按结束值):[0,2], [2,4], [3,6], [4,7]
处理[0,2]:a=0 > current_point(-1),选点2,count=1,current_point=2。
处理[2,4]:a=2 ≤ current_point(2),已覆盖,不选点。
处理[3,6]:a=3 > current_point(2),选点6,count=2,current_point=6。
处理[4,7]:a=4 ≤ current_point(6),已覆盖,不选点。
输出:2,符合样例。
代码样例
#include<bits/stdc++.h>
using namespace std;struct qj
{int a,b;
} d[10005];bool cmp(qj x,qj y)
{return x.b<y.b;
}int main()
{int n;cin>>n;for(int i=0; i<n; i++) cin>>d[i].a>>d[i].b;sort(d,d+n,cmp);int cnt=0,last=-1;for(int i=0; i<n; i++){if(d[i].a>last){cnt++;last=d[i].b;}}cout<<cnt;return 0;
}此代码仅供参考,请勿纯抄
(在此声明,思路为AI生成,代码本人所写)
