区间覆盖问题(贪心)

p1338区间覆盖问题(贪心之子问题)

子问题系列的贪心是一个很重要的贪心系列,可以用递归求解,虽然暂时不觉得会比普通循环好到哪里去

【问题描述】

  任务1:区间覆盖问题    数轴上有n闭区间[ai,bi],选择尽量少的区间覆盖一条指定线段[s,t]。

  任务2:覆盖区间问题
   数轴上有n闭区间[ai,bi],选择尽量少的闭区间[cj,dj]覆盖所有的闭区间[ai,bi],且[cj,dj]所包含的点不能有n个闭区间[ai,bi]之外的点。

这次贪心建立在左端点从左到右排序的基础上
问题一

先解决第一个问题,因为这是子问题系列的贪心:取一条右端点最右并且满足条件的线段,然后解决一个子问题,因此尝试递归(不一定最好)

void f(int i,int s,int t,int ans)//求s到t的距离,选择第了ns个,从第i个开始考虑 
状态怎么好写就怎么定义,不要太拘泥
{
    if(s>=t&&ans!=0)//有可能s=t
    {
        cout<<ans<<endl;
        return;
    }
    if(i==n+1)//排除无法覆盖情况1
    {
        cout<<-1<<endl;
        return;
    }
    if(p[i].a>s)//中间断开的情况(主要)
    {
        cout<<-1<<endl;
        return;
    }
    int sub=i,j;
    for(j=i+1;j<=n;j++)
    {
        if(p[j].a<=s)
            if(p[j].b>p[sub].b)
                sub=j;
        else break;
    }
    f(j,p[sub].b,t,ans+1);
}

这一段主要的问题就是判断无解比较考技术,不容易考虑到,会大家都会,但是通过率只有百分之二十

问题二
vector<data>v;//因为要先输出答案,因此只好想个办法存储
    int a=p[1].a,b=p[1].b;
    for(int i=1;i<=n;i++)
    {
        if(p[i].a<=b)
        {
            b=max(b,p[i].b);//这里可以选取最好的右端
        }
        else
        {
            v.push_back((data){a,b});
            a=p[i].a;
            b=p[i].b;
        }
    }
    v.push_back((data){a,b});//因为最后一段无法加入,要手工,用哨兵就有点扯了
    cout<<v.size()<<endl;
    for(int i=0;i<v.size();i++)
    {
        printf("%d %d\n",v[i].a,v[i].b);
    }

总结:这道题只是一个细节题,同时也有些新的手法值得积累,这个问题的类型倒是贪心中一个比较冷门的却有些难度的,顺便试试新开通的博客。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值