uva 10020 Minimal coverage

一直在想如何打植物大战僵尸,题目题意都没有好好理解。晚上静下心来才明白白天都想错了。实际上下午用了修改器发现pvz好无聊。

这是算法竞赛入门经典p233页中的区域覆盖问题,书本上讲的看了好久才懂,主要是我以为就只能用一条,实际上题意是用最少的条数组合起来。

写法就是排序和扫描,排序按左端点从小到大排。输入时先将右端点小于0的数据去掉,根本不可能用到。再进行一次预处理,找出第一段,要求左端点值小于等于0,右端点y1值最大。如果右端点y1已经大于m,可以结束了。否则进行下一轮选择,这次找的是左端点小于等于y1且右端点最大,再进行和上面一样的判断,直到找到答案或者发现无解。

#include<stdio.h>
#include<algorithm>
using namespace std;
const int N=100003;
struct da
{
    int x,y;
}a[N],b[N];

bool cmp(da a,da b)//结构体排序
{
    return a.x<b.x;
}

int main()
{
    int cas,i,n,m,j,cnt,s,e,pos,mix,temp,f;
    scanf("%d",&cas);
    while(cas--)
    {
        n=0;
        scanf("%d",&m);
        while(scanf("%d %d",&s,&e))
        {
            if(s==0&&e==0) break;
            if(e>=0){a[n].x=s;a[n].y=e;++n;}//处理输入数据
        }
        sort(a,a+n,cmp);//排序
        if(a[0].x>0) printf("0\n");//第一个区间起点就大于0,无解
        else
        {
            mix=cnt=pos=0;//cnt计数,mix选用点的序号
            for(pos=0;pos<n&&a[pos].x<=0;pos++)
                if(a[pos].y>a[mix].y) mix=pos;
            pos=mix;b[0].x=a[mix].x;b[0].y=a[mix].y;//第一段
            while(pos<n&&b[cnt].y<m)//判断是否一段可以完成
            {
                f=1;//标记有没有找到下一段
                temp=mix;//临时记录
                while(pos+1<n&&a[pos+1].x<=a[mix].y)
                {
                    f=0;
                    pos++;
                    if(a[pos].y>a[temp].y) temp=pos;
                }
                if(f) break;//没有找到答案结束寻找
                mix=temp;
                cnt++;b[cnt].x=a[mix].x;b[cnt].y=a[mix].y;
            }
            if(b[cnt].y>=m)//最右端大于m,有解
            {
                printf("%d\n",cnt+1);
                for(i=0;i<=cnt;i++)printf("%d %d\n",b[i].x,b[i].y);
            }
            else printf("0\n");
        }
        if(cas) printf("\n");
    }
    return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。http://xiang578.top/

转载于:https://www.cnblogs.com/xryz/p/4848093.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值