笨笨的西瓜种植(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
刚开始,我一见到这道题——哎呀,老熟人了~先按右端点排序,然后若这一个区间还要种植,若右端点没种过,那么种在最右,对所有拥有此端点的区间减去一个西瓜,然后标记右端点表示已经种了,并sum++,然后无论此次有没有种,都把右端点左移一位,以此类推,直到这个区间种完,继续下一个区间,第一次代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
using namespace std;
struct node
{
int b;
int e;
int t;
}S[3005];
int A[5005];
bool cmp(node p,node q)
{
if(p.e<q.e)
{
return 1;
}
return 0;
}
int sum;
int main()
{
//freopen("watermelon.in","r",stdin);
//freopen("watermelon.out","w",stdout);
int n,m;
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d %d %d",&S[i].b,&S[i].e,&S[i].t);
}
sort(S+1,S+m+1,cmp);
for(int i=1;i<=m;i++)
{
if(S[i].t>0)
{
if(A[S[i].e]==0)
{
S[i].t--;
for(int j=i+1;j<=m;j++)
{
if(S[i].e<=S[j].e&&S[i].e>=S[j].b&&S[j].t>0)
{
S[j].t--;
}
}
}
A[S[i].e]=1;
S[i].e--;
i--;
sum++;
}
}
printf("%d",sum);
}
然后很直接的错了……检查后发现了问题——如果这个点已经被种过,那么这个点会进不去循环,但是也会不应该的sum++和无谓的A[S[i].e]=1,所以如1 4 1,3 4 2,这种数据会错误,改了就对了:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
using namespace std;
struct node
{
int b;
int e;
int t;
}S[3005];
int A[5005];
bool cmp(node p,node q)
{
if(p.e<q.e)
{
return 1;
}
return 0;
}
int sum;
int main()
{
//freopen("watermelon.in","r",stdin);
//freopen("watermelon.out","w",stdout);
int n,m;
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d %d %d",&S[i].b,&S[i].e,&S[i].t);
}
sort(S+1,S+m+1,cmp);
for(int i=1;i<=m;i++)
{
if(S[i].t>0)
{
if(A[S[i].e]==0)
{
S[i].t--;
for(int j=i+1;j<=m;j++)
{
if(S[i].e<=S[j].e&&S[i].e>=S[j].b&&S[j].t>0)
{
S[j].t--;
}
}
A[S[i].e]=1;
sum++;
}
S[i].e--;
i--;
}
}
printf("%d",sum);
}