week3 区间覆盖

Title:数轴上有 n (1<=n<=25000)个闭区间 [xi, yi],选择尽量少的区间覆盖一条指定线段 [1, t]( 1<=t<=1,000,000)。覆盖整点,即(1,2)+(3,4)可以覆盖(1,4)。不可能办到输出-1

Input:
第一行:N和T
第二行至N+1行: 每一行一个闭区间。

Output:
选择的区间的数目,不可能办到输出-1

样例:
Input:
3 10
1 7
3 6
6 10

Output:
2

分析

  • 清除掉那些在线段[s,t]之外的区间,减少处理的区间量
  • 去除掉具有包含关系的小区间,同样也是减少处理的区间量
  • 对区间进行排序,按照x从小到大的顺序
  • 排序后,若第一个区间的x不等于s,说明不可能覆盖s点,也就是不可能覆盖这条指定的线段
  • 选择起点等于s的最长的一个区间max,进行覆盖。下一次选择区间时,起点应该置为max.y+1,选择起点小于等于max.y+1的最长区间,依此类推。直到将线段完全覆盖。
//now表示的是上一次已经覆盖到的最大点
//置起点now=s-1,即为起点的前一个点 
while(now<t)
{
 now++;//这一次进行覆盖需要从now的下一个点开始 
 找到起点小于等于now的最长区间max;
 if(没有找到) 说明覆盖失败,退出; 
 覆盖所用区间数++;
 now=max区间的y; 
} 

总结:假如覆盖到4,那么下一次应该是从5开始覆盖。[3,4],[5,6]是可以覆盖到[3,6]的。故每次选取区间[x,y]进行覆盖后,下一次覆盖应该从y+1开始。

备注:原题是将一天分成T个时间段,用1~T对时间段进行编号,给定n个区间进行覆盖。在此情境下,不会出现[1,T]之外的区间,故代码中并没有进行清除[1,T]之外的区间,也没有去掉具有包含关系的小区间。

#include<stdio.h>
#include<algorithm>
using namespace std;
#define range 25000
struct interval
{
 int x;
 int y;
};
int N = 0, T = 0, index = 0;
interval a[range];
bool com(const interval& a, const interval& b)
{
 return a.x<b.x;
}
int func()
{
 int i=0,now=0,max=0,number=0,maxi=0;
 while(now<T)
 {
  now++;  
     max=now; 
     maxi=-1;
  for(;i<N;i++)//找最长 
  {
   if(a[i].x<=now)
   {
    if(a[i].y>=max)
    {max=a[i].y;
    maxi=i;
    } 
   }
   else break; 
  }
  if(maxi== -1)
   return -1;
  number++;
  now=a[maxi].y;
 }
 return number;
}
int main()
{
 while (scanf("%d %d",&N,&T)!=EOF)
 {
  index=0; 
  while (index < N)
  {
   scanf("%d %d",&a[index].x,&a[index].y); 
   index++;
  }
  sort(a, a + N, com);
  if (a[0].x != 1)
   printf("-1\n");
  else
  {
   int number=func();
   if(number==-1)
       printf("-1\n");
   else printf("%d\n",number);
  }
 }
 return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值