UVA 10020 - Minimal coverage

                  RE了两次,又WA了一次,思路题永远都想不明白呀,这个题是lrj书上的区间覆盖问题,因为区间数量最少,所以无所谓这些解区间之间互相覆盖多少,首先那些在[0,m]外的区间没用,不用保存;可以预处理一下这些区间,做断点小于0的可以暂记为0,又区间比m大的,可以暂记为m;然后找区间是关键,每次都要找的区间在满足左端点<=起点的情况下右端点最大,这样既可以覆盖,又优先选择了大区域。节省了区间数量。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;
typedef struct Point
{
    int x,y;
    int xx,yy;
} Point;
Point p[100001];
int cmp(const void*_a,const void *_b)
{
    Point *a=(Point *)_a;
    Point *b=(Point *)_b;
    if(a->xx-b->xx)
        return a->xx-b->xx;
    else return a->yy-b->yy;
}
int main()
{
    //freopen("in.txt","r",stdin);
    int cas,m,n;
    scanf("%d",&cas);
    while(cas--)
    {
        scanf("%d",&m);
        n=0;
        while(scanf("%d%d",&p[n].x,&p[n].y)!=EOF&&(p[n].x||p[n].y))
        {
            if(p[n].x>=m||p[n].y<=0) ;
            else
            {
                p[n].xx=p[n].x<=0?0:p[n].x;
                p[n].yy=p[n].y<=m?p[n].y:m;
                n++;
            }
        }
        qsort(p,n,sizeof(p[0]),cmp);
        if(p[0].xx>0||n==0)
        {
            cout<<0<<endl;
            if(cas)
                cout<<endl;
            continue;
        }
        int begin=0;
        int num=0;
        int step[10020];
        int temp;
        while(1)
        {
            int max=0;
            temp=-1;
            for(int i=0; i<n; i++)
            {
                if(p[i].xx<=begin)
                {
                    if(p[i].yy>=max)
                    {
                        temp=i;
                        max=p[i].yy;
                    }
                }
            }
            step[num++]=temp;
            begin=p[temp].yy;
            if(begin==m)
                break;
            if(temp==-1)
                break;
        }
        if(begin!=m)
            cout<<0<<endl;
        else
        {
            cout<<num<<endl;
            for(int i=0; i<num; i++)
                cout<<p[ step[i]].x<<" "<<p[step[i]].y<<endl;
        }
        if(cas)
            cout<<endl;
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值