种树 (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.