【百练】P4151 电影节

P4151 电影节

题目链接:4151:电影节.

题目描述

总时间限制: 1000ms 内存限制: 65536kB

描述
大学生电影节在北大举办! 这天,在北大各地放了多部电影,给定每部电影的放映时间区间,区间重叠的电影不可能同时看(端点可以重合),问李雷最多可以看多少部电影。

输入
多组数据。每组数据开头是n(n<=100),表示共n场电影。
接下来n行,每行两个整数(0到1000之间),表示一场电影的放映区间
n=0则数据结束

输出
对每组数据输出最多能看几部电影

样例输入

8
3 4
0 7
3 8
15 19
15 20
10 15
8 18
6 12
0

样例输出

3

题解

方法一:贪心算法

思路

将所有电影按照结束时间从小到大进行排序,看的第一部电影选择结束时间最早的那部,然后接下来每次选择电影都应该满足:开始时间晚于上一部电影的结束时间且结束时间最早。

证明该贪心算法的有效性。

证明:(替换法)
假设使用贪心算法(也就是上述算法)得到的电影序列为: a 1 、 a 2 、 a 3 . . . a_1、a_2、a_3... a1a2a3...
不用该算法所挑选出来的最长电影序列为: b 1 、 b 2 、 b 3 . . . b_1、b_2、b_3... b1b2b3...

现证明:对于 ∀   i , b i {\forall}\ i,b_i  ibi 可以被替换为 a i a_i ai
对于电影 x x x x x x 的开始时间是 S ( x ) S(x) S(x),结束时间是 E ( x ) E(x) E(x)
使用数学归纳法:

  • i = 1 i=1 i=1
    因为 E ( a 1 ) ⩽ E ( b 1 ) E(a_1)\leqslant E(b_1) E(a1)E(b1),所以 b 1 b_1 b1 可以被替换为 a 1 a_1 a1
  • i > 1 i>1 i>1 时,假设 b i − 1 b_{i-1} bi1 可以被替换为 a i − 1 a_{i-1} ai1
    因为 E ( a i − 1 ) ⩽ E ( b i − 1 ) E(a_{i-1})\leqslant E(b_{i-1}) E(ai1)E(bi1) E ( b i − 1 ) ⩽ S ( b i ) E(b_{i-1})\leqslant S(b_i) E(bi1)S(bi),所以 E ( a i − 1 ) ⩽ S ( b i ) E(a_{i-1})\leqslant S(b_i) E(ai1)S(bi)
    由上述的贪心算法,可以知道: E ( a i ) = min ⁡ ( E ( x ) , x ∈ s e t ) , s e t = { x ∣ E ( a i − 1 ) ⩽ S ( x ) } E(a_i)=\min(E(x),x\in set),set=\{x|E(a_{i-1})\leqslant S(x)\} E(ai)=min(E(x),xset)set={xE(ai1)S(x)} 所以 E ( a i ) ⩽ E ( b i ) E(a_i)\leqslant E(b_i) E(ai)E(bi)
    又因为 b i − 1 b_{i-1} bi1 可以被替换为 a i − 1 a_{i-1} ai1
    所以 b i b_i bi 可以被替换为 a i a_i ai

综上,由数学归纳法,对于 ∀   i , b i {\forall}\ i,b_i  ibi 可以被替换为 a i a_i ai 得证。
所以该贪心算法有效。

对于上面的证明,你可能还有一个疑问,假如序列 b 1 、 b 2 、 b 3 . . . b_1、b_2、b_3... b1b2b3... 比序列 a 1 、 a 2 、 a 3 . . . a_1、a_2、a_3... a1a2a3... 要长,那么序列 b 1 、 b 2 、 b 3 . . . b_1、b_2、b_3... b1b2b3... 多出来的一部分无法被替换。

假设序列 a 1 、 a 2 、 a 3 . . . a_1、a_2、a_3... a1a2a3... 的最后一个元素为 a k a_k ak,序列 b 1 、 b 2 、 b 3 . . . b_1、b_2、b_3... b1b2b3... 存在 b k + 1 b_{k+1} bk+1,因为 b 1 、 b 2 、 b 3   . . .   b k b_1、b_2、b_3\ ...\ b_k b1b2b3 ... bk 已经被替换为了 a 1 、 a 2 、 a 3   . . .   a k a_1、a_2、a_3\ ...\ a_k a1a2a3 ... ak,所以 E ( a k ) ⩽ S ( b k + 1 ) E(a_k)\leqslant S(b_{k+1}) E(ak)S(bk+1),由上述贪心算法,序列 a 1 、 a 2 、 a 3 . . . a_1、a_2、a_3... a1a2a3... 的最后一个元素必定不是 a k a_k ak,因为 ∃   b k + 1 {\exists}\ b_{k+1}  bk+1,满足 E ( a k ) ⩽ S ( b k + 1 ) E(a_k)\leqslant S(b_{k+1}) E(ak)S(bk+1),那么 a k a_k ak 之后还会加入电影 a k + 1 a_{k+1} ak+1 到序列 a 1 、 a 2 、 a 3 . . . a_1、a_2、a_3... a1a2a3... 中,假设不成立。

算法

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

struct Film{
	int begin;
	int end;
	bool operator<(const Film& right)const{
		return end<right.end;
	}
};

int main(){
	int n;
	while(scanf("%d",&n),n!=0){
		vector<Film> films(n);
		for(int i=0;i<n;++i){
			scanf("%d %d",&films[i].begin,&films[i].end);
		}
		sort(films.begin(),films.end());
		int count=1;
		int endTime=films[0].end;
		for(int i=1;i<n;++i){
			if(films[i].begin>=endTime){
				++count;
				endTime=films[i].end;
			}
		}
		printf("%d\n",count);
	}
}

复杂度分析

假设电影节所放映的全部电影的场数为 n n n

  • 时间复杂度: O ( n log ⁡ n ) O(n\log n) O(nlogn),进行排序的时间复杂度为 O ( n log ⁡ n ) O(n\log n) O(nlogn),将所有电影遍历一遍 O ( n ) O(n) O(n),这两个程序段是并列的关系,所以总的时间复杂度为: O ( max ⁡ { n log ⁡ n , n } ) = O ( n log ⁡ n ) O(\max\{n\log n,n\})=O(n\log n) O(max{nlogn,n})=O(nlogn)
  • 空间复杂度: O ( n ) O(n) O(n)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值