笨笨的西瓜种植【贪心】

来源:互联网 发布:fs是什么软件 编辑:程序博客网 时间:2024/05/17 07:40

笨笨的西瓜种植(watermelon.cpp) 

【题目描述】

笨笨种了一块西瓜地,但这块西瓜地的种植范围是一条直线的…… 笨笨在一番研究过后,得出了m个结论,这m个结论可以使他收获的西瓜最多。 笨笨的结论是这样的: 从西瓜地B处到E处至少要种植T个西瓜,这个范围的收获就可以最大化。 笨笨不想那么辛苦,所以他想种植的西瓜尽量少,而又满足每一个所得的结论。

【输入】

第一行两个数n,m0<n<=5000,0<=m<=3000),表示笨笨的西瓜地长n,笨笨得出m个结论。 

接下来m行表示笨笨的m个结论,每行三个数b,e,t1<=b<=e<=n,0<=t<=e-b+1

【输出】

 输出笨笨最少需种植多少西瓜。

【输入样例】

9 4

1 4 2

4 6 2

8 9 2

3 5 2

【输出样例】

5


这道题是一道典型的“贪心”的题,也就是一个区间问题,只要按右端点排序再从每个右端点开始种就行了。排序后,依次从每个区间的左端点开始查找,记录已经种植的西瓜数量;如果该区间种植的数量不足T个西瓜,就把下一个的西瓜种在区间的最后位置,使得后面区间能共享到这些西瓜,保证西瓜种植的数量尽量少。
刚开始我在每个区间都从右端点开始种,却忘记了判重,所以某情况下在同一个地方种了几个西瓜尴尬。然后我加上一个判重的循环,程序会超时,我就写了一个函数判重,于是,就...AC了得意



代码如下:




#include<cstdio>
#include<cstring>
int i,j,t,k,sum,n,m;
int B[5005];
int E[5005];
int T[5005];//三个数组,左端点、右端点和种西瓜的个数
int f[5005],l;

void sortay(int x)//排序函数
{
if(x>m) return ;
for(int y=x+1;y<=m;y++)
if(E[x]>E[y])
{
t=B[x];B[x]=B[y];B[y]=t;
t=E[x];E[x]=E[y];E[y]=t;
t=T[x];T[x]=T[y];T[y]=t;
}
sortay(x+1);
}


bool checkay(int b)//判重函数
{
for(k=1;k<=sum;k++)
if(b==f[k])
return 1;
return 0;
}


int main()
{
//freopen("watermelon.in","r",stdin);
//freopen("watermelon.out","w",stdout);
scanf("%d%d",&n,&m);
for(i=1;i<=m;i++)
scanf("%d%d%d",&B[i],&E[i],&T[i]);
sortay(1);
for(i=1;i<=m;i++)
{
if(T[i]<=0) continue;
for(j=E[i];j>=B[i];j--)//从右端点E[i]开始往下种
{
if(checkay(j)) continue;
sum++;f[sum]=j;T[i]--;
for(k=i+1;k<=m;k++)//判断是否后面的区间能共享种的这个西瓜j
if(B[k]<=j&&j<=E[k])
T[k]--;
if(T[i]<=0) break;
}
}
printf("%d",sum);
return 0;
}

1 0
原创粉丝点击