用于个人学习记录
一、题目描述
二、方法介绍
- 以结构体形式存储每场比赛的数据(个人认为比起二维数组,这样更方便调用和查找数据)
- 排序
参加的每场比赛都不能有重合的时间,所以需要比较各个区间(理解为时间段)的比赛分布情况,即需要对比赛进行排序。按照结束时间或者起始时间都可以,我是按照结束时间排序的。
排序方法这里我选用的是快速排序(默认升序)
- 首先设立一基准值,将大于或等于基准值的数集中到数组右边,小于基准值的数集中到数组左边
- 此时左右两侧的数组可以独立出来以相同的方法继续处理(递归),最后得到一个升序的有序数组
C语言代码实现
//一开始存储选择的基准值,之后找到需重新排位的数可以直接赋值到对应的区间
void Quick_sort1(int a[], int left, int right) {
if (left >= right)//这种情况下left和right之间已经没有需要排序的数,可以直接返回
return;
int begin = left, end = right;
int povit = begin, key = a[begin];//一开始选用begin作为起始坑(即可被覆盖的数),所以先把key保存(记录)下来
while (begin < end) {
//从右开始找小于基准的数(因为一开始的基准选在了第一个位置,这个位置的数应小于key)
while (begin < end && a[end] >= key) {
end--;
}//找到后填入左边的坑中
a[povit] = a[end];
povit = end;//此时这个位置应填入比key大的数,所以成为了新坑
//同理此时坑靠右需要小于key的数,所以开始从左向右找
while (begin < end && a[begin] <= key) {
begin++;
}//找到后填入坑中,并再次更新坑
a[povit] = a[begin];
povit = begin;
}
a[povit] = key;//相遇位置一定为坑(不然出不了循环)
Quick_sort1(a, left, povit - 1);
Quick_sort1(a, povit + 1, right);
}
三、题解
对于排序后如何选取区间的分析
- 结束时间相同,起始时间不同
只要该比赛起始时间没有与上一场比赛重合就没有分别,选哪个都一样。
- 起始时间相同,结束时间不同
这种情况我们在排序之后不需要考虑,因为我们是按照结束时间升序排序,从前往后遍历选取要参加的比赛,所以会选择结束时间更早的比赛,这样使剩余的时间更多,可以参加更多的比赛。
- 两场比赛无重合时间,则从前往后选取
只要排序后从前往后选取比赛(使此时参加的最后一场比赛的结束时间尽量靠前),就能选取到最优解
- 两场比赛时间重复,不合题意舍弃结束时间靠后的
代码实现
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
struct comp {//构造结构体
int start;
int end;
};
void Quick_sort1(struct comp a[], int left, int right) {
if (left >= right)
return;
int begin = left, end = right;
int povit = begin, key = a[begin].end, key1 = a[begin].start;
while (begin < end) {
while (begin < end && a[end].end >= key) {
end--;
}
a[povit] = a[end];
povit = end;
while (begin < end && a[begin].end <= key) {
begin++;
}
a[povit] = a[begin];
povit = begin;
}
a[povit].end = key;
a[povit].start = key1;
Quick_sort1(a, left, povit - 1);
Quick_sort1(a, povit + 1, right);
}
int main()
{
int n = 0;
scanf("%d", &n);
struct comp a[1000];
for (int i = 0; i < n; i++) {
scanf("%d %d", &a[i].start, &a[i].end);
}
Quick_sort1(a, 0, n - 1);
int count = 1, end = a[0].end;
for (int i = 1; i < n; i++) {
if (a[i].start < end)//说明比赛时间重合,不参加
continue;
else {
count++;
end = a[i].end;//更新此时最后的结束时间
}
}
printf("%d", count);
return 0;
}