1214 线段覆盖
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 黄金 Gold
题目描述 Description
给定x轴上的N(0<N<100)条线段,每个线段由它的二个端点a_I和b_I确定,I=1,2,……N.这些坐标都是区间(-999,999)的整数。有些线段之间会相互交叠或覆盖。请你编写一个程序,从给出的线段中去掉尽量少的线段,使得剩下的线段两两之间没有内部公共点。所谓的内部公共点是指一个点同时属于两条线段且至少在其中一条线段的内部(即除去端点的部分)。
输入描述 Input Description
输入第一行是一个整数N。接下来有N行,每行有二个空格隔开的整数,表示一条线段的二个端点的坐标。
输出描述 Output Description
输出第一行是一个整数表示最多剩下的线段数。
样例输入 Sample Input
3
6 3
1 3
2 5
样例输出 Sample Output
2
数据范围及提示 Data Size & Hint
0<N<100
分析 Analysis
这道题需要证明贪心。
“易证,该题适用贪心策略” qwq
我翻到的题解就是这么跟我说的 qwq
“显然,该题适用贪心策略” qwq
横批:缺少优雅 qwq
...
首先按升序排序右端点,定义 last 为决策区间的起点(通常为已决策区间的最远端点-1)
那么从小到大遍历右端点,第一个满足不重叠条件的线段即可添加
这个地方就需要证明贪心了,那么根据我的想法:
右端点是层层推进的,那么越早决策右端点,留给下一次决策的可决策区间就越大
(我们的决策区间其实就是最左端和最右端)
并且可以保证之前的决策不会影响到后面的决策
(也就是满足最优子结构?欢迎指正)
还是觉得不够优雅 qwq 欢迎路过的大牛解惑呀
代码 Code
1 #include2 #include 3 #include 4 using namespace std; 5 6 struct edge{ 7 int l,r,val; 8 }e[10000]; 9 10 bool cmp(const edge &a,const edge &b){11 return a.r < b.r;12 }13 14 int main(){15 int n,a,b;16 scanf("%d",&n);17 18 for(int i = 1;i <= n;i++){19 scanf("%d%d",&a,&b);20 if(a > b) swap(a,b);21 e[i].l = a+2000;22 e[i].r = b+2000;23 }24 25 sort(e+1,e+1+n,cmp);26 27 int last = 0,ans = 0;28 for(int i = 1;i <= n;i++){29 if(e[i].l > last) ans++,last = e[i].r-1;30 }31 32 printf("%d",ans);33 34 return 0;35 }