唉,怎么现在才开始写哪……………
唉……
好吧,开始我的第一篇博文《线段覆盖》(此处省略无数个寒酸……)
先看一眼题:
问题描述
——给定x轴上的n(0<n<100)条线段。每个线段由它的两个端点ai和bi确定,i=1,2,…,n。这些坐标都是区间(-999,999)的整数。有些线段之间会互相交叠或覆盖。请你写一个程序,从给出的线段中去掉尽量少的线段,使得剩下的线段两两之间没有内部公共点。所谓内部公共点是枕一个点同时属于两条线段且至少在其中一条线段的内部(即除去端点的部分)。
输入:
第一行一个整数n;
接下来n行,每行有两个空格隔开的整数ai,bi,表示第i条线段的两个端点的坐标。
输出:
第一行一个整数表示最多剩下的线段数。接下来的每行两个数表示一条剩下的线段,注意按坐标升序排列。如果有多个解,只输出其中一个解。
SAMPLE INPUT
3
6 3
1 3
2 5
SAMPLE OUTPUT
2
1 3
3 6
好,那题目就是这样,不用眨眼就能看出这是一道贪心的裸题
但我还是看了好久才看了出来,可能真的是我太困了吧……
那怎么贪心呢
于是我们看到,每个线段都有一个起点坐标和终点坐标,而且题目允许起终点重合,那我们就会想到之前做过的那道《活动选择》。那主要思路就是先按照线段的尾端点排序一下(注意!由于输入时没有规定前后端点,所以输入之后要判断大小,而且输出也需要调换顺序,所以一举两得。)。排序之后我们还需要判断上一个线段的尾端点是否大于当前线段的首端点。最后输出数字
这样题就结束啦
下面附上代码
1 #include<bits/stdc++.h>//请原谅我在用万能头文件…… 2 using namespace std; 3 const int size=100010; 4 struct edge { 5 int l,r; 6 } l[size]; //用于存首尾端点的结构体 7 bool cmp(const edge&a,const edge &b) { 8 return a.r<b.r; 9 } 10 int main() { 11 //freopen("cover.in","r",stdin); 12 //freopen("cover.out","w",stdout); 13 int n; 14 cin >> n; 15 for(int i=1; i<=n; ++i) { 16 cin >> l[i].l>>l[i].r; 17 if(l[i].l>l[i].r)swap(l[i].l,l[i].r);//判断首端点尾端点大小 18 } 19 sort(l+1,l+1+n,cmp);//结构体的快排 20 int ans=0; 21 for(int i=1,last=-2333; i<=n; i++) { 22 if(last<=l[i].l) { 23 //cout <<l[i].l<< l[i].r<<endl; 24 last=l[i].r; 25 ans++; 26 } 27 } 28 cout<<ans<<endl; 29 for(int i=1,last=-2333; i<=n; i++) { 30 if(last<=l[i].l) { 31 cout <<l[i].l<< ' '<<l[i].r<<endl; 32 last=l[i].r; 33 ans++; 34 } 35 } 36 return 0; 37 }