第1部分 基础算法(提高篇)--第1章 贪心算法-贪心算法-1423:【例题2】种树

1423:【例题2】种树

时间限制: 1000 ms 内存限制: 65536 KB
提交数: 2746 通过数: 1087
【题目描述】
现在我们国家开展新农村建设,农村的住房建设纳入了统一规划,统一建设,政府要求每一住户门口种些树。门口路边的地区被分割成块,并被编号成1…N。每个部分为一个单位尺寸大小并最多可种一棵树。每个居民房子门前被指定了三个号码B,E,T。这三个数表示该居民想在B和E之间最少种T棵树。当然,B≤E,居民必须记住在指定区不能种多于区域地块数的树,所以T≤E-B+l。居民们想种树的各自区域可以交叉。你的任务是求出能满足所有要求的最少的树的数量,尽量较少政府的支出。

【输入】
第一行包含数据N,M,区域的个数(0

下面的m行描述居民们的需要:B E T,0

【输出】
输出一个数,为满足所有居民的要求,所需要种树的最少数量。

【输入样例】
9 4
3 5 2
1 4 2
4 6 2
8 9 2
【输出样例】
5


思路:按照区间的结束位置从小到大排序。然后从区间1到区间n进行选择:对于当前区间,若集合中的数不能覆盖它,则将区间末尾的数加入集合。种树要种得少,就要使一棵树给多个区间使用。这样,尽量在重叠区间种树即可,而重叠位置一定是在区间尾部。对下一个区间,看差多少棵就在该区间尾部种多少。

#include
#include
#include
#include
#include
#include

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;
}

你可能感兴趣的:(信息学C++,一本通)