ZOJ4120 贪心加优先队列
题目大意:
在二维坐标系中给出n条线段,第i条线段的两个端点分别为(li,i)和(ri,i),每个整数点都可以被标记,但是被标记的点x坐标不能相同,求至少有一个点被标记的线段最多有多少条
基本思路:贪心+优先队列
1.要使标记的线段最多,一条线段上只需标记一个点
2.尽可能标记短的线段,使更多线段可以被标记
3. 先对所有线段按左端点从小到大,左端点相同时按右端点从小到大的顺序进行排序
4.可选线段中左端点最小,且在与它左端点相同的所有线段中右端点最小的线段,标记左端点,对于与它左端点相同的其他线段则只能标记该点之后的点->优先队列
5.队首线段左端点可标记则出队,计数器加一,若队首线段左端点已被标记,则将该线段左端点加一后再入队(保证左端点小于等于右端点)
Sample Input
2 3 1 2 1 1 2 3 3 1 2 1 1 2 2
Sample Output
3 2
1 #include<iostream> 2 #include<cstdio> 3 #include<queue> 4 #include<cstring> 5 #include<cmath> 6 #include<algorithm> 7 #define ll long long 8 using namespace std; 9 struct Segment 10 { 11 int l, r;//左右端点x坐标 12 friend bool operator<(Segment a,Segment b) 13 { 14 if (b.l == a.l) 15 return a.r > b.r; 16 return a.l > b.l; 17 } 18 }; 19 priority_queue<Segment> q; 20 int main() 21 { 22 int T, n, ans, x, y; 23 scanf("%d", &T); 24 while (T--) 25 { 26 ans = 0; 27 while (!q.empty())//清空队列 28 q.pop(); 29 scanf("%d", &n); 30 while (n--) 31 { 32 Segment t; 33 scanf("%d%d", &x, &y); 34 t.l = x; 35 t.r = y; 36 q.push(t);//将所有线段加入队列 37 } 38 int k = 0;//k记录上一个被标记的点的x坐标 39 while (!q.empty()) 40 { 41 Segment u = q.top(); 42 q.pop(); 43 if (u.l == k)//若左端点已被标记,则左端点x坐标加一 44 { 45 u.l++; 46 if (u.l <= u.r)//得到的新线段符合要求则入队 47 q.push(u); 48 } 49 else//若左端点没被标记,则k记为左端点,计数器加一 50 { 51 k = u.l; ans++; 52 } 53 } 54 printf("%d\n", ans); 55 } 56 return 0; 57 }

浙公网安备 33010602011771号