区间覆盖问题 题解

【问题描述】

    给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.

 

posted @ 2015-05-08 16:39  PbTfcLx  阅读(250)  评论(0编辑  收藏  举报