今晚把困扰了好久的贪心题做出来了,给大家分享一下思路。
题目描述
一条街的一边有几座房子。因为环保原因居民想要在路边种些树。路边的地区被分割成块,并被编号成1..N。每个部分为一个单位尺寸大小并最多可种一棵树。每个居民想在门前种些树并指定了三个号码B,E,T。这三个数表示该居民想在B和E之间最少种T棵树。当然,B≤E,居民必须记住在指定区不能种多于区域地块数的树,所以T≤E-B+l。居民们想种树的各自区域可以交叉。你的任务是求出能满足所有要求的最少的树的数量。
写一个程序计算最少要种树的数量。
输入
第一行包含数据N,区域的个数(0<N≤30000);
第二行包含H,房子的数目(0<H≤5000);
下面的H行描述居民们的需要:B E T,0<B≤E≤30000,T≤E-B+1。
输出
树的数目。
样例输入
复制样例数据
9
4
1 4 2
4 6 2
8 9 2
3 5 2
样例输出
5
- 贪心性质:尽可能少的种树,重复部分越多越好,故先按起始位置排序,具体代码如下:
-
#include <stdio.h> #include <algorithm> #include <stdlib.h> #include <iostream> using namespace std; struct tree { int B; int E; int T; }t[50000]; bool cmp(tree a,tree b) { return a.B<b.B; } int main() { int cnt=0; int m,n; int H; scanf("%d%d",&n,&H); for(int i=1;i<=H;i++) scanf("%d%d%d",&t[i].B,&t[i].E,&t[i].T); sort(t+1,t+H+1,cmp); int z=t[1].E; cnt+=t[1].T;//第一个起始位置最靠前可以想象成从后往前排,想种多少种多少。 for(int i=2;i<=H;i++) { if(t[i].B<=z)//判断是否可以重复 { if(t[i].E<=z)//如果是他的一个子区间 { if(t[i-1].T>=t[i].T) continue; else cnt+=t[i].T-t[i-1].T; } else { int ans=z-t[i].B+1;//从第下一个的开始到上一个的结束可以种多少 if(ans>=t[i].T)//可以种下,则重复部分最大 continue; else { cnt+=t[i].T-ans;//否则补上差的数 z=z+t[i].T-ans;//末位置改变 } } } else//不可以重复直接加就可以了。 { cnt+=t[i].T; z=t[i].E;//末点位置改变。 } } printf("%d\n",cnt); return 0; }