【NOIP普及组】2016年模拟考试(9.3)——笨笨的西瓜种植
二、笨笨的西瓜种植(watermelon.cpp)
【题目描述】
笨笨种了一块西瓜地,但这块西瓜地的种植范围是一条直线的…… 笨笨在一番研究过后,得出了m个结论,这m个结论可以使他收获的西瓜最多。 笨笨的结论是这样的: 从西瓜地B处到E处至少要种植T个西瓜,这个范围的收获就可以最大化。 笨笨不想那么辛苦,所以他想种植的西瓜尽量少,而又满足每一个所得的结论。
【输入】
第一行两个数n,m(0<n<=5000,0<=m<=3000),表示笨笨的西瓜地长n,笨笨得出m个结论。
接下来m行表示笨笨的m个结论,每行三个数b,e,t(1<=b<=e<=n,0<=t<=e-b+1)
【输出】
输出笨笨最少需种植多少西瓜。
【输入样例】
9 4
1 4 2
4 6 2
8 9 2
3 5 2
【输出样例】
5
------------------------------------------------------------------------------------------------------
此题和NOIP的整数区间十分像,只不过加了一个“长度”和“个数”,怎么处理呢?
它增加了一个长度n之后,我原来以为n没有任何卵用,但是,确实没有什么卵用!
所以,我们只需要处理“个数”就行了:
处理个数嘛,就简单了,加个v数组存次数(个数),每次查一下,查到了就--,在进入循环时判断一下(v!=0)就行了。
就是整数区间的方法了:
按照“右端点”(输入中的e)进行排序,注意:当“右端点”一样时,一定要判断“左端点”(b)。
然后,就是j从“右端点”开始,每次符合条件就进入,sum++,查后面的“区间”中有没有此数,有,v就--。
好像没说清楚……大家看代码吧:
#include<cstdio> #include<algorithm> using namespace std; struct k { int b; int e; int v; }wl[3002];//定义结构体更方便 int n,m; int v[5002];//这里的“v”和结构体里的“v”不同,是用来看第i块地有没有种西瓜,种了肯定就不能再种 int cmp(k x,k y) { if(x.e!=y.e) return x.e<y.e; else return x.b<y.b; } int main() { freopen("watermelon.in","r",stdin); freopen("watermelon.out","w",stdout);//文件输入输出 scanf("%d%d",&n,&m); for(int i=0;i<m;i++) scanf("%d%d%d",&wl[i].b,&wl[i].e,&wl[i].v); sort(wl,wl+m,cmp);//本来我习惯自己“sort”,结果没“sort”出来 int sum=0; for(int i=0;i<m;i++) for(int j=wl[i].e;j>=wl[i].b;j--) if(v[j]==0&&wl[i].v>0)//判断 { sum++; v[j]=1; for(int k=i;k<m;k++) if(j<=wl[k].e&&j>=wl[k].b)//我之前傻到还加了一个for循环让p从b到e来比较…… wl[k].v--; } printf("%d",sum); return 0; }