首页 > 代码库 > uva 10020- Minimal coverage (贪心思想 简单区间覆盖)

uva 10020- Minimal coverage (贪心思想 简单区间覆盖)

题目大意:给出一个范围M,然后给出若干的区间,以0 0 终止, 要求用最少的区间将0 ~M 覆盖,输出最少个数以及方案。

解题思路:典型的区间覆盖问题,算法竞赛入门经典P154上有讲。

/*author: charkj_z */
/*time: 0.108s */
/*rank: 674 */
/*为什么不把没用的地方去掉? 因为去掉了我觉得不像我能写出来的*/
/*Ac code : */

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
const int maxn=100010;
struct qujian
{
    int x;
    int y;
}s[maxn];

bool cmp(const qujian a,const qujian b)
{
    if(a.x!=b.x) return a.x<b.x;
    else
        return a.y<b.y;
}
int n,cnt,order,vis[maxn];
void input()
{
    int p,q;
    n=cnt=0;
    scanf("%d",&order);
    while(scanf("%d%d",&p,&q)!=EOF)
    {
        if(p==0&&q==0)
            break;
        s[n].x=p;
        s[n].y=q;
        n++;
    }
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(s,0,sizeof(s));
        memset(vis,0,sizeof(vis));
        input();

        sort(s,s+n,cmp);/*结构体排序,两个升序,不解释*/
        int begin=0,max,id;
        for(int i=0;i<n;i++)
        {
            if(s[i].x>order)
                break;
            max=0;
            int k;
            for(int k=0;k<n-i;k++)
            /*我说下面有i+k,这样就能明白了k<n-i了吧。已经不再需要前面去掉的区间了,节省一丢丢时间*/
            {
                if(s[i+k].x>begin)
                /*对于开始和中间每一步,这个判断都是适合的
                若当前最靠左的区间左端点已经超出所覆盖区间右端点,无法继续覆盖*/
                {
                    k--;
                    printf("k = %d\n",k);
                    break;
                }
                if(s[i+k].y>max)
                /*在上面的if的前提下,即可以覆盖的前提下,找出可用区间中区间最靠右的区间
                更新最当前最大值,同时用id记录下该区间坐标*/
                {
                    max=s[i+k].y;
                    id=i+k;
                }
            }
            if(k>0)/*直接跳过在上面循环中去掉的不符合的区间*/
                i+=k;
            if(max<begin)/*如果当前可选区间的最右端依然触不到上一次的最右端
                说明区间发生中断,区间覆盖不成功*/
                break;

            begin=max;/*更新当前最右端*/
            vis[cnt++]=id;/*vis数组是标记数组,用来记录所选区间*/

            if(begin>=order)/*边界条件,达到此条件时覆盖成功,跳出循环*/
                break;
        }
        /*输出格式不解释*/
        if(max>=order)
        {
            printf("%d\n",cnt);
            for(int i=0;i<cnt;i++)
            {
                printf("%d %d\n",s[i].x,s[i].y);
            }
        }
        else
            printf("0\n");
        if(t)
            printf("\n");
    }
    return 0;
}