洛谷P1803 凌乱的yyy / 线段覆盖 详细解析以及AC代码(附额外测试用例+贪心算法解析)

前言

好!也是学贪心必经之路,背包+线段覆盖(或者是任务分配问题)。也算半个模板题了,理解好本题对于学好贪心算法肯定是基础。

题目

凌乱的yyy / 线段覆盖

题目背景

快 noip 了,yyy 很紧张!

题目描述

现在各大 oj 上有 n n n 个比赛,每个比赛的开始、结束的时间点是知道的。

yyy 认为,参加越多的比赛,noip 就能考的越好(假的)。

所以,他想知道他最多能参加几个比赛。

由于 yyy 是蒟蒻,如果要参加一个比赛必须善始善终,而且不能同时参加 2 2 2 个及以上的比赛。

输入格式

第一行是一个整数 n n n,接下来 n n n 行每行是 2 2 2 个整数 a i , b i   ( a i < b i ) a_{i},b_{i}\ (a_{i}<b_{i}) ai,bi (ai<bi),表示比赛开始、结束的时间。

输出格式

一个整数最多参加的比赛数目。

样例 #1

样例输入 #1

3
0 2
2 4
1 3

样例输出 #1

2

提示

  • 对于 20 % 20\% 20% 的数据, n ≤ 10 n \le 10 n10
  • 对于 50 % 50\% 50% 的数据, n ≤ 1 0 3 n \le 10^3 n103
  • 对于 70 % 70\% 70% 的数据, n ≤ 1 0 5 n \le 10^{5} n105
  • 对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 1 0 6 1\le n \le 10^{6} 1n106 0 ≤ a i < b i ≤ 1 0 6 0 \le a_{i} < b_{i} \le 10^6 0ai<bi106

题目分析

  这类任务分配或者说线段覆盖问题首先要搞清楚数量和总量的区别。这里是贪心算法一般都是要求数量尽可能多,那么我们就要摒弃生活中惯用的总量优先原则,那么就比较好理解局部的最优解。
  讲得太深奥我举一个例子,比如说本题要求的是数量最多多少。如果存在0-1、9-100-10两组,我们会优先选择前者,因为在同样的0-10的时间里,前者有两个大于后者的一个。但是根据我们的普遍思维是求的总量的话,明显是后者能够充分利0-10的时间。这就是数量和总量的差别。
  理解了前面的,你就可以很容易理解为什么我们本题的局部最优解是结束时间最早。因为结束的越早相当于我们的选择越多,我们也更加可以插入越多的比赛,跟开始时间无关(当然首先不能交叉),跟总时间也无关(事实上我们希望时间越短,时间短的极有可能是最优解)。
  原理搞清楚,那么本题就简单了。将比赛按照时间顺序排序,写一个循环使得每次都选取符合条件且结束时间最早的比赛直至最后一个比赛或者没有符合条件的比赛。
  具体代码见后文(附注释)

注意事项

1.sort快排函数也可以使用在结构体里,上一题不太清楚,也是学习了一下别人的代码,但是需要自己写一个cmp的比较函数。不过并不困难。
2.本题数量级在106级别,使用冒泡或者选择排序时间复杂度将超过1012次方,按照一秒109次计算来算,肯定会超时,所以我们需要选择时间复杂度更小的算法,比如快速排序。
3.需要理解为什么局部最优解是选取结束时间最短的比赛,这是本题贪心算法的关键,具体解析看题目解析。
4.数组要开大一点,不然就像我一样RE了。

代码

耶

完整代码如下:

#include<bits/stdc++.h>
using namespace std;
struct game {
	int start,end;
} a[1000007],t;
bool cmp(game x,game y)
{
	return x.end<y.end;
}
int main()
{
	int n,count=1,flag=1;
	cin>>n;
	for(int i=0; i<n; i++)
		cin>>a[i].start>>a[i].end;
//按照结束时间排序
	sort(a,a+n,cmp)	;
	int earliest=0;//当前最早结束时间
	while(earliest!=n&&flag) { //当是最后一个或者没有符合条件的时候退出
		flag=0;
		for(int i=earliest; i<n; i++)
			if(a[i].start>=a[earliest].end) {
				earliest=i; //更新earliest
				count++;//计数加1
				flag=1;//说明有符合条件的
			}
	}
	cout<<count;
	return 0;
}

后话

错误题解

数组小 加上 没有觉察到必须使用非n2的排序 导致超时和运行错误
哭了
相关解决方法在注意事项中已详细说明。

额外用例

输入

输入比较长我绑定到开头了,大家可以自行下载测试

输出

343

卑微求三连

如果感觉本文帮到你那就请你给一个免费的赞、收藏和关注吧!

题目来源

洛谷链接

  • 9
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值