1423:【例题2】种树
1423:【例题2】种树
题解
【思路点拨】
首先按照区间的结束位置从小到大排序。然后从区间1到区间n进行选择:对于当前区间,若集合中的数不能覆盖它,则将区间末尾的数加入集合
贪心策略:取最后一个。
种树要种得少,就要使一棵树给多个区间使用。这样,尽量在重叠区间种树即可,而重叠位置一定是在区间尾部。
处理问题时,先按所有区间的结束位置排序,之后依次处理每个区间,先在第一个区间尾部种满足要求的树,对下一个区间,看差多少棵就在该区间尾部种多少
代码
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<string> using namespace std; int n,m,ans=0,t,k=0; bool vis[50000]; struct app { int s,e,v; }a[5005]; bool cmp(app x,app y) { return x.e <y.e ; } int main() { memset(vis,0,sizeof(vis)); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) scanf("%d%d%d",&a[i].s ,&a[i].e ,&a[i].v ); sort(a+1,a+m+1,cmp); for(int i=1;i<=m;i++) { k=0; for(int j=a[i].s ;j<=a[i].e ;j++) //遍历种了多少树 if(vis[j]) k++; if(k>=a[i].v ) continue; //该区间树已种够 else { for(int z=a[i].e ;z>=a[i].s;z--) //从区间后面往前补 { if(!vis[z]) { k++; ans++; vis[z]=1; if(k>=a[i].v ) break; //补够即停 } } } } printf("%d",ans); return 0; }