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