区间覆盖问题 题解

【问题描述】

    给n个闭区间[ai,bi],选择尽量少的区间覆盖一条指定线段[s,t]。

【样例输入】

      1 10

     7

     2 5

     1 4

     3 8

     3 10

     7 10

     4 6

     1 3

【样例输出】

       2

【解题思路】

     首先,我们可以将bi小于s的数据都去除,因为这些都是无用的,这样可以减少一些时间复杂度。然后以ai为关键字从小到大进行排序,r赋值为b[1],从第二个开始取,如果当前的ai比上一个取的区间的bi小,记录下当前的bi,选择最大的bi所占的区间,更新r,直到r>=t。

【代码实现】

 1 type rec=record

 2      a,b:longint;

 3 end;

 4 var c:array[1..1000] of rec;

 5     i,n,s,t,ans,j,r,pos,max:longint;

 6     y:rec;

 7 procedure sort(l,r: longint);

 8       var

 9          i,j,x: longint;

10          y:rec;

11       begin

12          i:=l;

13          j:=r;

14          x:=c[(l+r) div 2].a;

15          repeat

16            while c[i].a<x do

17             inc(i);

18            while x<c[j].a do

19             dec(j);

20            if not(i>j) then

21              begin

22                 y:=c[i];

23                 c[i]:=c[j];

24                 c[j]:=y;

25                 inc(i);

26                 j:=j-1;

27              end;

28          until i>j;

29          if l<j then

30            sort(l,j);

31          if i<r then

32            sort(i,r);

33       end;

34 begin

35  readln(s,t);

36  readln(n);

37  for i:=1 to n do

38   with c[i] do

39    begin

40     readln(a,b);

41     if b<=s then

42      a:=maxlongint;//预处理

43    end;

44  sort(1,n);

45  if c[1].a>s then//如果最小的ai比s大,那么s必定无法被覆盖,因此无解

46   begin

47    writeln('No answer');

48    halt;

49   end;

50  r:=c[1].b;pos:=1;ans:=1;//减少时间复杂度,设pos变量,从上一个所取的区间的后一个开始取

51  repeat

52   max:=0;

53   for i:=pos+1 to n do

54    if (c[i].a<=r)and(c[i].b>max) then

55     begin

56      pos:=i;

57      max:=c[i].b;

58     end;

59   r:=max;

60   inc(ans);

61  until r>=t;

62  writeln(ans);

63 end.

 

你可能感兴趣的:(题解)