P1803 凌乱的yyy / 线段覆盖题解

用于个人学习记录

一、题目描述

 二、方法介绍

  • 以结构体形式存储每场比赛的数据(个人认为比起二维数组,这样更方便调用和查找数据)
  • 排序

参加的每场比赛都不能有重合的时间,所以需要比较各个区间(理解为时间段)的比赛分布情况,即需要对比赛进行排序。按照结束时间或者起始时间都可以,我是按照结束时间排序的。

排序方法这里我选用的是快速排序(默认升序)

  1. 首先设立一基准值,将大于或等于基准值的数集中到数组右边,小于基准值的数集中到数组左边
  2. 此时左右两侧的数组可以独立出来以相同的方法继续处理(递归),最后得到一个升序的有序数组

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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值