种树(贪心思想)

题目描述

某条街被划为 n 条路段,这 n 条路段依次编号为 1…n。每个路段最多可以种一棵树。现在居民们给出了 h 组建议,每组建议包含三个整数 b,e,t,表示居民希望在路段 b 到 e 之间至少要种 t 棵树。这些建议所给路段的区间可以交叉。请问:如果要满足所有居民的建议,至少要种多少棵树。

输入格式

第一行为 n,表示路段数。

第二行为 h,表示建议数。

下面 hhh 行描述一条建议:b,e,t,用一个空格分隔。

输出格式

输出只有一个数,为满足所有居民的建议,所需要种树的最少数量。

样例

样例输入

9
4
1 4 2
4 6 2
8 9 2
3 5 2

样例输出

5

数据范围与提示

30% 的数据满足 0<n≤1000,0<h≤500;

100% 的数据满足 0<n≤3×10^4,h≤5000,0<b≤e≤3×10 ^ 4,t≤e-b+1。

思路:

首先题目要求是居民想种的树的各自区域可以相交,并且请你求出能够满足所有居民的要求,需要种树的最少数量,所以就可以想到尽量在相交的部分种树可以使种树的数量最少。由于每位居民与上一位居民的相交处位于上一位居民的尾部,所以我们可以考虑从尾部开始种树。排序的过程是先按照每户居民的结束位置从小到大排列,如果结束位置相等,则按照开始位置从大到小排列。

#include<stdio.h>
#include<math.h>
#include<string.h>
int main()
{
    int n,h,k,l,p,a[10001][5],b[100001];
    int ans=0;
    memset(b,0,sizeof(b));//数值为0则表示没有种树,为1则表示已经种了树。
    scanf("%d",&n);
    scanf("%d",&h);
    for(int i=0;i<h;i++)
        scanf("%d%d%d",&a[i][0],&a[i][1],&a[i][2]);
    for(int i=0;i<h;i++){                         //将结束位置从小到大排序
        for(int j=0;j<h-1;j++){
            if(a[j][1]>a[j+1][1]){
                k=a[j][0],a[j][0]=a[j+1][0],a[j+1][0]=k;
                k=a[j][1],a[j][1]=a[j+1][1],a[j+1][1]=k;
                k=a[j][2],a[j][2]=a[j+1][2],a[j+1][2]=k;
            }
            if(a[j][1]==a[j+1][1]){
                if(a[j][0]<a[j+1][0]){
                k=a[j][0],a[j][0]=a[j+1][0],a[j+1][0]=k;
                k=a[j][1],a[j][1]=a[j+1][1],a[j+1][1]=k;
                k=a[j][2],a[j][2]=a[j+1][2],a[j+1][2]=k;
                }
            }
        }
    }
    for(int i=0;i<h;i++){
        int sum=0;
        for(int j=a[i][0];j<=a[i][1];j++)
            sum+=b[j];//sum表示在这段区间上已经种的树的数目
        for(int j=a[i][1];j>=a[i][0]&&sum<a[i][2];j--)//倒着种树
        {
            if(b[j]!=1){//如果没种树
                b[j]=1;//种树
                sum++;//这段区间上的树+1
                ans++;//总的数量+1            }
        }
    }
}
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43328040/article/details/85016927
今日推荐