题目
原题:https://www.luogu.com.cn/problem/P6244
题目描述
FJ 参加活动。
他想参加尽可能多的 N 个活动,参加完某个之后可以立刻参加下一个。
给定 FJ 可参加的活动列表、其开始时间 T 和持续时间 L ,求 FJ 可以参加的最大活动数。
FJ 每个活动都不会提早离开。
输入格式
第一行有一个整数 N。
第二到 N+1 行:每行包含两个用空格分隔的整数 T 和 L ,意义如上述。
输出格式
输出仅一行,FJ 最多能参加几个活动。
输入输出样例
输入 #1
7 1 6 8 6 14 5 19 2 1 8 18 3 10 6
输出 #1
4
说明/提示
1≤T,L≤105
1≤N≤104
题解
很经典的贪心问题:先对每个活动按结束时间排序,然后循环判断每个活动是否与已选择的活动重叠,如果不重叠就选择这个活动。
#include<bits/stdc++.h>
using namespace std;
typedef struct event{ //活动结构体
int begin,end,last;
}event;
event e[10010];
int n,cnt;
bool b[10010];
bool cmp(const event& a,const event& b){ //排序的cmp函数
if(a.end!=b.end) return (a.end<b.end);
return (a.begin<b.begin);
}
bool is_cd(const event& a,const event& b){ //是否重叠
if(a.end<=b.begin) return 0;
return 1;
}
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%d%d",&e[i].begin,&e[i].last),e[i].end=e[i].begin+e[i].last;
sort(e,e+n,cmp); //按结束时间排序
for(int i=0;i<n;i++){ //如果没有重叠
if(b[i]==0){ //把重叠的活动都标记为1
for(int j=0;j<n;j++){
if(b[j]==0&&is_cd(e[i],e[j])) b[j]=1;
}
cnt++; //可以参加的活动数目加1
}
}
printf("%d\n",cnt); //输出答案
return 0;
}