种树 (codevs 1653) 题解

【问题描述】

    一条街的一边有几座房子。因为环保原因居民想要在路边种些树。路边的地区被分割成块,并被编号为1..n。每个块大小为一个单位尺寸并最多可种一棵树。每个居民想在门前种些树并指定了三个号码b,e,t。这三个数表示该居民想在b和e之间最少种t棵树。当然b<=e,居民必须保证在指定地区不能种多于地区被分割成块数的树,即要求t<=e-b+1。允许居民想种树的各自区域可以交叉。出于资金短缺的原因,环保部门请你求出能够满足所有居民的要求,需要种树的最少数量。 

【样例输入】

        9

      4

      1 4 2

      4 6 2

      8 9 2

      3 5 2

【样例输出】

        5

【解题思路】

      本题用贪心算法,先以b为关键字排序,然后从后往前种,因为这样与后面的重合的可能性才越大,定义一个布尔型数组,每种一棵,就赋为true,最后计算true的数量即可。

【代码实现】

 1 type rec=record
 2      b,e,t:longint;
 3 end;
 4 var a:array[1..30000] of rec;
 5     f:array[1..30000] of boolean;
 6     i,j,n,m,ans:longint;
 7 procedure sort(l,r:longint);
 8 var i,j,x:longint;
 9     y:rec;
10 begin
11  i:=l;
12  j:=r;
13  x:=a[(l+r) div 2].e;
14  repeat
15   while a[i].e<x do
16    inc(i);
17   while x<a[j].e do
18    dec(j);
19   if not(i>j) then
20    begin
21     y:=a[i];
22     a[i]:=a[j];
23     a[j]:=y;
24     inc(i);
25     j:=j-1;
26    end;
27  until i>j;
28  if l<j then
29   sort(l,j);
30  if i<r then
31   sort(i,r);
32 end;
33 function pd(t:longint):longint;
34 var i,ans:longint;
35 begin
36  ans:=0;
37  for i:=a[t].b to a[t].e do
38   if f[i] then inc(ans);
39  exit(ans);
40 end;//判断当前区间种了几棵树
41 procedure hh;
42 var t,tt:longint;
43 begin
44  for t:=1 to n do
45   begin
46    if pd(t)<a[t].t then
47     begin
48      tt:=a[t].e;f[tt]:=true;
49     end;
50    while pd(t)<a[t].t do//还没种完,继续往前种
51     begin
52      dec(tt);
53      f[tt]:=true;
54     end;
55   end;
56 end;
57 begin
58  readln(m);
59  readln(n);
60  for i:=1 to n do
61   with a[i] do
62    readln(b,e,t);
63  sort(1,n);
64  hh;
65  for i:=1 to m do
66   if f[i] then
67    inc(ans);
68  writeln(ans);
69 end.

 

你可能感兴趣的:(种树 (codevs 1653) 题解)