A.活动安排
题目描述
设有 n个活动的集合 E={1,2,…,n}其中每个活动都要求使用同一资源,如演讲会场等,而在同一时间内只有一个活动能使用这一资源。每个活动 i 都有一个要求使用该资源的起始时间si 和一个结束时间fi 且ai<ji。如果选择了活动 i,则它在时间区间 [si,fi)[内占用资源。若区间[si,fi)与区间不相交[sj,fj),则称活动 i与活动 j 是相容的。也就是说,fi≤sj当或 fj≤si时,活动 i 与活动 j 相容。选择出由互相兼容的活动组成的最大集合。
输入格式
第一行一个整数 n;
接下来的 n 行,每行两个整数 si,fi
输出格式
输出互相兼容的最大活动个数。
样例
样例输入
4
1 3
4 6
2 5
1 7
样例输出
2
解析:按结束时间从小到大排序,若后面活动的开始时间大于等于上一个的前面活动的结束时间即可
#include <bits/stdc++.h>
using namespace std;
struct str
{
int s,f;
}l[1005];
int cmp(str n,str m)
{
return n.f<m.f;
}
int main()
{
int n,a,ans=1;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d%d",&l[i].s,&l[i].f);
}
sort(l,l+n,cmp);
a=l[0].f;
for(int j=1;j<n;j++){
if(l[j].s>=a){
a=l[j].f;
ans++;
}
}
printf("%d",ans);
return 0;
}
B. 种树
题目描述
某条街被划为 n 条路段,这 n 条路段依次编号为 1…n。每个路段最多可以种一棵树。现在居民们给出了 h 组建议,每组建议包含三个整数 b,e,t,表示居民希望在路段 bb到 ee 之间至少要种 t 棵树。这些建议所给路段的区间可以交叉。请问:如果要满足所有居民的建议,至少要种多少棵树。
输入格式
第一行为 n,表示路段数。
第二行为 h,表示建议数。
下面 hh 行描述一条建议:b, e, t用一个空格分隔。
输出格式
输出只有一个数,为满足所有居民的建议,所需要种树的最少数量。
解析: 若想得到最优解,尽量在每个集合的交集处种树,则该树可以为多个集合所用,最后的树将是最小的,首先将集合按末尾点从小到大排列,然后用一个数组记录该点有没有种树,并且种树是从后往前种,保证在交集处种。
代码
#include <bits/stdc++.h>
using namespace std;
struct L
{
int b,e,t;
}l[5005];
int cmp(L x,L y)
{
return x.e<y.e;
}
int main()
{
int n,h,ans=0;
int l1[30005];
scanf("%d %d",&n,&h);
for(int i=0;i<h;i++){
scanf("%d%d%d",&l[i].b,&l[i].e,&l[i].t);
}
memset(l1,0,sizeof(l1)); //数组清零,注意memset函数第二个参数只能填0或-1
sort(l,l+h,cmp);
for(int j=0;j<h;j++){
for(int k=l[j].b;k<=l[j].e;k++){
if(l[j].t==0){
break;
}
if(l1[k]==1){
l[j].t--;
}
}
for(int q=l[j].e;q>=l[j].b;q--){
if(l[j].t==0){
break;
}
if(l1[q]==0){
l1[q]=1;
ans++;
l[j].t--;
}
}
}
printf("%d",ans);
return 0;
}