uva10020 贪心
题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=961
题目大意:给你一个0~m的区间,然后给你若干线段,问你最少取多少线段可以将0~m完全覆盖
思路分析:贪心思想,(我不贪心所以没做出来),首先给出的线段有一些是没有用的,可以在输入的时候就将这些线段略去,
然后可以按照线段右端点从大到小排序,开始枚举更新右端点,初始时右端点为0(左右端点重合),然后开始枚举这些线段,寻找一条
能够覆盖原有右端点同时能够最大限度更新右端点的线段,并标记这条线段为已用,更新右端点,如果找不到满足的纠结束,最后看右端点是否>m
即可
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn=100000+100; struct node { int l; int r; }line[maxn]; bool cmp(node a,node b) { return a.r>b.r; } int m; bool vis[maxn]; int ans[maxn]; int main() { int T; scanf("%d",&T); while(T--) { scanf("%d",&m); int x,y; int tot=0; while(scanf("%d%d",&x,&y)&&(x||y)) { if(y<=0||x>=m) continue; line[tot].l=x; line[tot++].r=y; } sort(line,line+tot,cmp); //cout<<tot<<endl; int sr=0; memset(vis,false,sizeof(vis));//用来标记该线段有没有被使用 memset(ans,0,sizeof(ans)); int ant=0; while(sr<m) { bool flag=false;//判断是否找到 for(int i=0;i<tot;i++) { if(!vis[i]&&line[i].l<=sr&&line[i].r>sr) { vis[i]=true; ans[ant++]=i; sr=line[i].r;//更新右端点 flag=true; } } //cout<<sr<<endl; if(!flag) break;//未找到符合条件的线段 } if(sr>=m) { printf("%d\n",ant); for(int i=0;i<ant;i++) { printf("%d %d\n",line[ans[i]].l,line[ans[i]].r); } } else printf("0\n"); } }