实验10相容问题
问题:
有n项活动申请使用同一个礼堂,每项活动有一个开始时间和一个截止时间。如果任何两个活动不能同时举行,问如何选择这些活动,从而使得被安排的活动数量达到最多。
解析:
如果我们选择开始时间最早的节目,得不到最优解
如果我们选择时间最短的节目,也无法得到最优解
可以用数学归纳法证明,我们的贪心策略应该是每次选取结束时间最早的活动。
直观上也很好理解,按这种方法选择相容活动为未安排活动留下尽可能多的时间。
所以,我们的贪心策略是按照节目的结束时间排序。
设计(核心代码):
1 bool cmp(const node &a,const node &b) 2 { 3 return a.e<b.e; 4 } 5 6 sort(p + 1, p + 1 + n, cmp); 7 int ans = 0, tmp = -1; 8 for (int i = 1; i <= n; ++i) 9 { 10 if (p[i].s >= tmp) ans++, tmp = p[i].e; 11 }
分析:
复杂度:$O( n log(n) )$
源码:
https://github.com/Big-Kelly/Algorithm
1 #include<bits/stdc++.h> 2 #include <set> 3 #include <map> 4 #include <stack> 5 #include <cmath> 6 #include <queue> 7 #include <cstdio> 8 #include <string> 9 #include <vector> 10 #include <cstring> 11 #include <iostream> 12 #include <algorithm> 13 14 #define ll long long 15 #define PLL pair<ll,ll> 16 #define PII pair<int,int> 17 #define bug printf("*********\n") 18 #define FIN freopen("input.txt","r",stdin); 19 #define FON freopen("output.txt","w+",stdout); 20 #define IO ios::sync_with_stdio(false),cin.tie(0) 21 #define ls root<<1 22 #define rs root<<1|1 23 24 using namespace std; 25 const int inf = 0x3f3f3f3f; 26 const ll Inf = 1e14 + 7; 27 const int maxn = 1e5 + 5; 28 const int mod = 1e9 + 7; 29 30 struct node 31 { 32 int s, e; 33 }p[maxn]; 34 35 bool cmp(const node& a, const node& b) 36 { 37 return a.e < b.e; 38 } 39 40 int main() 41 { 42 int n; 43 while (~scanf("%d", &n), n) 44 { 45 for (int i = 1; i <= n; ++i) scanf("%d %d", &p[i].s, &p[i].e); 46 sort(p + 1, p + 1 + n, cmp); 47 int ans = 0, tmp = -1; 48 for (int i = 1; i <= n; ++i) 49 { 50 if (p[i].s >= tmp) ans++, tmp = p[i].e; 51 } 52 printf("%d\n", ans); 53 } 54 }