ural 1303 Minimal Coverage(贪心)
链接:
http://acm.timus.ru/problem.aspx?space=1&num=1303
按照贪心的思想,每次找到覆盖要求区间左端点时,右端点最大的线段,然后把要求覆盖的区间改为这个右端点到M这个区间。依次类推下去,这样的话就只需要扫一遍就可以找去来。
要做的预备工作就是将线段按照左端点的升序排序就可以了。
它的时间复杂度就是O(n)
代码一直WA,望大神指教
1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 #include<map> 5 #include<vector> 6 #include<set> 7 #include<stack> 8 #include<queue> 9 #include<algorithm> 10 #include<cmath> 11 #include<stdlib.h> 12 using namespace std; 13 #define MAX(a,b) (a > b ? a : b) 14 #define MIN(a,b) (a < b ? a : b) 15 #define MAXN 200005 16 #define INF 1000000007 17 #define mem(a) memset(a,0,sizeof(a)) 18 #define judge(i) (ma[i].l<=L && ma[i].r>=L && ma[i].l != ma[i].r)//判断是否覆盖了点L 19 20 struct node{int l,r;}ma[MAXN]; 21 int ans[MAXN]; 22 int M,N,T; 23 int L; 24 25 int cmp(node a,node b) 26 { 27 if(a.l != b.l)return a.l<b.l; 28 else return a.r<b.r; 29 } 30 31 32 33 int find_index(int s,int &i)//找到覆盖了点L而且右端点最大的点,并返回; 34 //同时将后面要覆盖的点设置为它的右端点 35 { 36 i = s; 37 int e = s,endd = ma[i].r; 38 while(i < N && judge(i) ) 39 { 40 if(ma[i].r > endd) 41 { 42 endd = ma[i].r; 43 e = i; 44 } 45 i++; 46 } 47 L = endd;//endd就是满足覆盖条件下的最大的右端点 48 //并将其设置为下次比较的左端点 49 return e;//返回此次的线段的下标 50 } 51 52 int main() 53 { 54 while(~scanf("%d",&M)) 55 { 56 N=0; 57 int i; 58 mem(ans); 59 while(scanf("%d%d",&ma[N].l, &ma[N].r) && (ma[N].l || ma[N].r)) 60 { 61 if(ma[N].r <=0 || ma[N].l>=M)ma[N].l = ma[N].r = INF;//吧在要求区间两端之外的线段去掉 62 //吧它的左右端点值赋值为INF,这样的话排序时自然就会到最后方,也就相当于不用考虑 63 N++; 64 } 65 sort(ma,ma+N,cmp); 66 67 L = 0;//最初要被覆盖的点是0 68 int num = 0; 69 for(i=0;i<N;i++) 70 { 71 int t = i+1;//将t设置为i+1,如果下面的judge成功,就会进入函数的while中,那么i会++,如果不成功,t=i+1 72 if(judge(i)) ans[num++] = find_index(i,t); 73 i = t-1;//由于t相当于多+了1,所以-1 74 if(L >= M)break;//一旦找到,就退出循环 75 } 76 if(L < M)printf("No solution\n"); 77 else 78 { 79 printf("%d\n",num); 80 for(i=0;i<num;i++) 81 { 82 printf("%d %d\n",ma[ans[i]].l,ma[ans[i]].r); 83 } 84 } 85 } 86 return 0; 87 }