美文网首页
贪心:区间类问题

贪心:区间类问题

作者: 淇漯草 | 来源:发表于2020-09-14 00:22 被阅读0次

题目:选N个课程,每个课程开始和结束时间分别是a, b
问:分身成几个人,可以完美上所有课程?

区间贪心版

#include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>

using namespace std;

struct node
{
    int m_begin_time;
    int m_end_time;
    int m_flag = false;
};

int Compare(const node &a, const node &b){
    return a.m_begin_time == b.m_begin_time ? a.m_end_time < b.m_end_time : a.m_begin_time < b.m_begin_time;
}

int CountBlock(vector<node> &courses, int depth){
    if(courses.size() == 0){
        return depth;
    }else if(courses.size() == 1){
        return depth + 1;
    }
    vector<int> cluster;
    int start = courses[0].m_begin_time;
    int end = courses[0].m_end_time;
    cluster.push_back(0);
    for(int i=1; i<courses.size(); i++){
        if(courses[i].m_begin_time >= end){
            cluster.push_back(i);
            start = courses[i].m_begin_time;
            end = courses[i].m_end_time;
        }
    }
    for(int i=cluster.size()-1; i>=0; i--){
        courses.erase(courses.begin() + cluster[i]);
    }
    return CountBlock(courses, depth+1);
}

int main()
{
    int N;
    cin >> N;
    vector<node> courses(N);
    for(int i=0; i<N; i++){
        cin >> courses[i].m_begin_time;
        cin >> courses[i].m_end_time;
    }
    sort(courses.begin(), courses.end(), Compare);
    cout << CountBlock(courses, 0);
    return 0;
}

染色版

#include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>

using namespace std;

/*
 * 题目:选N个课程,每个课程开始和结束时间分别是a, b
 * 问:分身成几个人,可以完美上所有课程?
 * 采用染色的方法
*/


int main()
{
    int N;
    cin >> N;
    vector<int> my_time(1000000, 0);
    int begin, end;
    int max_end = 0;
    for(int i=0; i<N; i++){
        cin >> begin >> end;
        max_end = max(max_end, end);
        for(int j=begin; j<end; j++){
            my_time[j]++;
        }
    }
    int max_count = 0;
    for(int i=0; i<=end; i++){
        max_count = max(max_count, my_time[i]);
    }
    cout << max_count;
    return 0;
}

染色离散化版

#include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>

using namespace std;

/*
 * 题目:选N个课程,每个课程开始和结束时间分别是a, b
 * 问:分身成几个人,可以完美上所有课程?
 * 思路:
 * 1.将所有课程左端点排序。
 * 2.根据贪心,查找出不冲突的区间号,区间个数。
 * 3.去掉这些不冲突的区间号。回到2(因为不需要再次排序)
 *
 * 只通过了%50.
 * 优化点1:vector数组的erase非常消耗大,优化上可以考虑用标记来解决。(优化后没解决)
 * 优化点2:采用list容器,可以降低删除的成本。(重新写代码有点困难,因为操作方式不同)
 * 
*/


struct node
{
    int m_begin_time;
    int m_end_time;
    int m_flag = false;
};

int Compare(const node &a, const node &b){
    return a.m_begin_time == b.m_begin_time ? a.m_end_time < b.m_end_time : a.m_begin_time < b.m_begin_time;
}

int main()
{
    int N;
    cin >> N;
    vector<node> courses(N);
    vector<int> all_count;
    for(int i=0; i<N; i++){
        cin >> courses[i].m_begin_time;
        cin >> courses[i].m_end_time;
        courses[i].m_end_time--;
        all_count.push_back(courses[i].m_begin_time);
        all_count.push_back(courses[i].m_end_time);
    }
    sort(all_count.begin(), all_count.end());
    int key = unique(all_count.begin(), all_count.end())-all_count.begin();//内部实现
    int color[key+7];
    memset(color, 0, sizeof(color));
    for (int i=0; i<N; i++) {
        int L = lower_bound(all_count.begin(), all_count.begin()+key, courses[i].m_begin_time) - all_count.begin();
        int R = lower_bound(all_count.begin(), all_count.begin()+key, courses[i].m_end_time) - all_count.begin();
        color[L]++;
        color[R+1]--;
    }
    for (int i = 1; i<key; i++) {
        color[i] = color[i-1]+color[i];
    }
    int ans = 0;
    for (int i = 0; i<key; i++){
        ans = max(ans, color[i]);
    }
    cout << ans;
}

优先队列时间线版

#include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
#include <queue>

using namespace std;


struct node
{
    int m_begin_time;
    int m_end_time;
    int m_flag = false;
};

int Compare(const node &a, const node &b){
    return a.m_begin_time == b.m_begin_time ? a.m_end_time < b.m_end_time : a.m_begin_time < b.m_begin_time;
}

int main()
{
    int N;
    cin >> N;
    vector<node> courses(N);
    vector<int> all_count;
    for(int i=0; i<N; i++){
        cin >> courses[i].m_begin_time;
        cin >> courses[i].m_end_time;
    }
    sort(courses.begin(), courses.end(), Compare);
    priority_queue<int, vector<int>, greater<int> > pri_queue;
    for(int i=0; i<N; i++){
        if(pri_queue.empty()){
            pri_queue.push(courses[i].m_end_time);
        }else{
            auto smallest = pri_queue.top();
            if(smallest <= courses[i].m_begin_time){// 无需开一条时间线
                int temp = courses[i].m_end_time;
                pri_queue.pop();
                pri_queue.push(temp);
            }
            else{//开一条新的时间线
                pri_queue.push(courses[i].m_end_time);
            }
        }
    }
    cout << pri_queue.size();
}

相关文章

  • 贪心:区间类问题

    题目:选N个课程,每个课程开始和结束时间分别是a, b问:分身成几个人,可以完美上所有课程? 区间贪心版 染色版 ...

  • 贪心算法

    贪心区间

  • 区间贪心

    问题描述 数轴上有n个开区间(ai,bi),尽量选择多个区间,是的这些区间两两之间没有共同点。 输入格式 第一行的...

  • 贪心-区间覆盖

    例题: 数轴上有n个闭区间[ai,bi],选择尽量少的区间覆盖一条指定的线段[s,t]。 思路: 枚举所有可用区间...

  • 贪心--合并区间

    目录[https://www.jianshu.com/p/85e18c21317a] 题号[https://lee...

  • 贪心

    区间贪心 POJ 2376: Cleaning Shifts选择尽量少的区间覆盖一段线段。将所有区间按照左端点升序...

  • 区间贪心算法

    给出N个开区间(x,y),从中选择尽可能多的开区间,使得这些开区间两两没有交集。 区间被包含,选择区间长度短的 区...

  • 贪心十八:合并区间

    题目地址: https://leetcode-cn.com/problems/merge-intervals/[...

  • 线段树和树状数组学习日志

    oneDay 为什么要使用线段树因为对于某一类问题,我们关心的就只是线段(区间) 线段树的一些经典问题区间染色问题...

  • 贪心算法基础

    应用场景 所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。 饼干分孩子问题 去除交叉区间 股票...

网友评论

      本文标题:贪心:区间类问题

      本文链接:https://www.haomeiwen.com/subject/bxlaektx.html