POJ 3190 贪心+优先队列

本文介绍了一种基于贪心算法的课程安排方法,通过合理分配课程时间,最大化利用资源,避免课程间时间冲突。采用左端点递增排序策略,确保课程紧密衔接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这道题受到了以前做过的一道题目的影响,有n节课,每节课都有一个开始结束时间,求出一天中最多可以上多少节课,使得任意两节课时间不冲突。这道题目是按照结束时间递增的时间排序。

刚开始碰到这道题我就有感觉和以前那道题差不多,毕竟对于每一个stall,都是尽量的使得里面的区间最多。所以我就按照结束时间排序了。

但是这道题目怎么写呢?按照贪心的思想,我们肯定是想要每一个stall都是尽量满的,这样一来,使用的stall就会更少。所以假如现在已经有了n个stall,我们在考虑一个区间。我们该把这个区间放到哪个stall中去呢?还是我们要新增一个stall来放置这个区间?

为了使得空间尽量的不浪费,我们选择n个stall中剩余空间最大的那个来装置这个区间,如果可以装的下,就装在这里。如果装不下,那么其他的也装不下,我们就新增一个stall来安置这个区间。

但是这样一想,我们刚才按照结束时间排序的策略就不太合适了,我们想要所有区间排列的尽量紧密,那么我们应该先考虑左端点小的区间,这样才能结合的更紧密。也就是我们一开始要按照左端点递增来排序。

#include <map>
#include <queue>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define MAX_N 50005

using namespace std;

struct data
{
    int l, r;
    int id;
    bool operator < (const data& b) const
    {
        return l < b.l;
    }
};
data dat[MAX_N];
typedef pair<int, int> pii;//每个stall最后一个区间的结束时间,这个stall的编号
priority_queue<pii, vector<pii>, greater<pii> > stalls;

int main()
{
    //freopen("in.txt", "r", stdin);

    int N;
    int stall_id[MAX_N];//保存每个区间所在stall的编号
    while (scanf("%d", &N) != EOF)
    {
        for (int i = 1; i <= N; i++)
        {
            scanf("%d%d", &dat[i].l, &dat[i].r);
            dat[i].id = i;
        }
        sort(dat + 1, dat + N + 1);

        int cnt = 1;
        stalls.push(pii(dat[1].r, cnt));
        stall_id[dat[1].id] = cnt;
        for (int i = 2; i <= N; i++)
        {
            int ok = 0;
            if (!stalls.empty())
            {
                pii t = stalls.top();
                if (t.first < dat[i].l)
                {
                    t.first = dat[i].r;
                    stalls.pop();
                    stalls.push(pii(t));
                    stall_id[dat[i].id] = t.second;
                    ok = 1;
                }
            }
            if (!ok)
            {
                cnt++;
                stalls.push(pii(dat[i].r, cnt));
                stall_id[dat[i].id] = cnt;
            }
        }

        printf("%d\n", cnt);
        for (int i = 1; i <= N; i++)
            printf("%d\n", stall_id[i]);
    }

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值