区间贪心/贪心排序/线段覆盖的贪心策略/一段时间内观看最多节目

引子

什么是线段覆盖的贪心策略?

怎么理解线段覆盖的贪心策略?

区间贪心排序例题

在这里插入图片描述
在这里插入图片描述

题目

在这里插入图片描述

分析

根据引子里学到的知识,我们这里在读入保存好所有数据之后,应该按照每个vtuber结束时间从小到大进行排序,可以用引子例题中sort+cmp进行排序,然后在学习过程中发现了一种新的方法,推荐给大家:
结构体内嵌比较函数bool operator * (const node *x) const {}

之后设置现在时间now=-1,依次处理.
如果读入数据的结束时间大于我们观看的结束时间,说明我们已经没有可以观看的节目了,break退出;
如果读入数据的开始时间大于等于现在时间now,观看,并把现在时间now设为这个节目的结束时间,循环计数即可

见代码

代码

#include<bits/stdc++.h>
#define maxn 1001
using namespace std;

struct show{
	int start;//直播开始和结束时间 
	int end;
	string name;//主播名字 
	bool operator<(const show &a)const{
		return end<a.end;//按结束时间从小到大排序,见分析处链接
	}
}vtuber[maxn];

vector<string> str;//记录观看直播的主播名字

int main(){
	int n;//有几个处理数据
	int endtime;//结束观影时间
	scanf("%d %d",&n,&endtime);
	for(int i=1;i<=n;i++){
		cin>>vtuber[i].start>>vtuber[i].end>>vtuber[i].name;
	}
	sort(vtuber+1,vtuber+n+1);
	int now=-1,ans=0;//现在时间为-1,最大观影数为0
	for(int i=1;i<=n;i++){
		if(vtuber[i].end>endtime)	break;//超过结束观影时间,退出循环
		if(vtuber[i].start>=now){//如果这一场在我么观影时间内(开始时间符合+结束时间符合)
			ans++;
			str.push_back(vtuber[i].name);//记录主播名字
			now=vtuber[i].end;//把现在时间设为观看后的时间 
		} 
	} 
	printf("%d\n",ans);
	for(int i=0;i<str.size();i++) cout<<str[i]<<endl;
	return 0;
}

用pair化简版本的代码

其中
activities[i].second.first=开始时间
activities[i].first=结束时间//按这个排序
activities[i].second.second=主播名字

sort对pair排序时默认对第一个升序排序,第一个相同对第二个升序排序
代码来源:SSPU-ACM2020预选赛 C题(贪心)

#include <bits/stdc++.h>
using namespace std;
typedef pair<int, string> p;
typedef pair<int, p> Acti; //活动结构体
int main()
{
    int n, t, a, b, end = 0; //end是当前活动时间,初始值为0,起始时间大于或等于当前时间的活动均为可选活动
    cin >> n >> t;
    Acti activities[n];
    string ans[n];
    for (int i = 0; i < n; i++)
        cin >> activities[i].second.first >> activities[i].first >> activities[i].second.second;
    sort(activities, activities + n);//step1:对活动的结束时间排序(因为需要按起始时间顺序输出,就直接把整个结构体排了吧)
    int count = 0;
    for (int i = 0; i < n; i++)                
        if (activities[i].second.first >= end) //step2:对排序后的活动,如果开始时间大于或等于上一个选中活动的结束时间,则选出该活动.
        {
            if (activities[i].first > t) //当活动中的结束时间大于活动结束的时刻就停止
                break;
            ans[count++] = activities[i].second.second;
            end = activities[i].first; //当前活动时间更新
        }
    cout << count << endl;
    for (int i = 0; i < count; i++)
        cout << ans[i] << endl;
}

猜你喜欢

转载自blog.csdn.net/beta___/article/details/107910460