UVa 10020 - Minimal coverage

29 篇文章 0 订阅
基本思路:已知目标线段[0,m],在所有给出线段左端点值小于目标线段左端点值的线段中,选出所对应右端点值最大的点,并用y的值不断更新左端点的值,直到y值大于M,跳出。
在做之前需要预处理一下,将与目标线段无交集的线段全部滤去,并判断给出的左右线段的最右值和最左值是否能将目标线段覆盖。

代码如下:

#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;

struct point
{
    int x, y;
} pot[100002];
int cmp(const void *a, const void *b) //先按x的值排序再按y的值排序
{
    point *aa = (point *)a;
    point *bb = (point *)b;
    if(aa->x != bb->x)
        return aa->x > bb->x ? 1 : -1;
    return aa->y > bb->y ? 1 : -1;
}
int y_cmp(const void *a, const void *b) //按y的值排序
{
    point *aa = (point *)a;
    point *bb = (point *)b;
    return aa->y > bb->y ? 1 : -1;
}
int mem[200002];
int main()
{
#ifdef test
    freopen("in.txt", "r", stdin);
#endif
    int t, m, i;
    scanf("%d", &t);
    while(t--)
    {
        int ct, flagx = 0, flagy = 0;
        int mct = 0;
        scanf("%d", &m);
        for(ct = 0;; ct++)
        {
            scanf("%d%d", &pot[ct].x, &pot[ct].y);
            if(!pot[ct].x && !pot[ct].y)  
                break;
            if(pot[ct].y <= 0 || pot[ct].x >= m) // 若线段在目标线段的两边,直接略去,不存
                ct--;
            else
            {
                if(pot[ct].x <= 0) //需要给出的线段的最左端的值有小于0的值
                    flagx = 1;
                if(pot[ct].y >= m) //需要给出的线段的最右端的值有大于M的值
                    flagy = 1;
            }
        }
        int l = 0, fi = 0;
        if(flagx && flagy && ct == 1) //满足条件,且只有一条线段,则直接输出
            printf("1\n%d %d\n", pot[0].x, pot[0].y);
        else if(flagx && flagy) 
        {
            qsort(pot, ct, sizeof(pot[0]), cmp); 
            int ff = 0;
            while(l < m) //在所有给出线段左端点值x<目标线段左端点值的线段中,选出所对应y最大的点,并用y的值不断更新左端点的值,直到y值大于M,跳出
            {
                for(i = fi; i < ct; i++)
                    if(pot[i].x > l && i > 0&& pot[i - 1].y < pot[i].x) //若中间有一段目标线段是所给线段无法覆盖的,则跳出返回0
                    {
                        ff = 1;
                        printf("0\n");
                        break;
                    }
                    else if(pot[i].x > l)
                        break;
                qsort(&pot[fi], i - fi, sizeof(pot[0]), y_cmp); //按y值排序
                mem[++mct] = pot[i - 1].x;
                mem[++mct] = pot[i - 1].y;
                l = pot[i - 1].y;
                fi = i;
                if(ff)
                    break;
            }
            if(ff)
            {
                puts("");
                continue;
            }
            printf("%d\n", mct / 2);
            for(int i = 1; i <= mct; i+=2)
                printf("%d %d\n", mem[i], mem[i + 1]);
        }
        else
            printf("0\n");
        if(t)
            puts("");
    }
    return 0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值