第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<N≤30000),房子的數目(0<m≤5000);

下面的m行描述居民們的需要:B E T,0<B≤E≤30000,T≤E-B+1。

【輸出】
輸出一個數,爲滿足所有居民的要求,所需要種樹的最少數量。

【輸入樣例】
9 4
3 5 2
1 4 2
4 6 2
8 9 2
【輸出樣例】
5


思路:按照區間的結束位置從小到大排序。然後從區間1到區間n進行選擇:對於當前區間,若集合中的數不能覆蓋它,則將區間末尾的數加入集合。種樹要種得少,就要使一棵樹給多個區間使用。這樣,儘量在重疊區間種樹即可,而重疊位置一定是在區間尾部。對下一個區間,看差多少棵就在該區間尾部種多少。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章