Stall Reservations(贪心算法)--学习笔记

问题描述

有 n头牛(1<=n<=50,000)要挤奶。给定每头牛挤奶的时间区
间[A,B] (1<=A<=B<=1,000,000,A,B为整数)。
牛需要呆畜栏里才能挤奶。一个畜栏同一时间只能容纳一头牛。
问至少需要多少个畜栏,才能完成全部挤奶工作,以及每头牛都放哪个畜栏里(Special judged)
去同一个畜栏的两头牛,它们挤奶时间区间哪怕只在端点重合也是不可以的。

贪心算法

在这里,我们所有的奶牛都需要挤奶,到了一个奶牛的挤奶时,就必须要为这个奶牛寻找。

S(x)表示奶牛x的开始时间。E(x)表示x的结束时间。对E(x), x可以是奶牛,也可以是畜栏。畜栏的结束时间,就是正在其里面挤奶的奶牛的结束时间。同一个畜栏的结束时间是不断在变的。

解题思路
1:把奶牛按照挤奶开始时间从前往后排序
2:为第一头奶牛分配畜栏
3:依次处理后面的每一头奶牛,处理第i头奶牛时候,考虑已分配畜栏中结束时间最早的畜栏x。
若畜栏结束时间<奶牛开始时间,则不用分配新的畜栏,i可以进入x,并修改畜栏结束时间为E(i)
若畜栏结束时间>=奶牛开始时间,则分配新的畜栏,E(i)
直到所有奶牛处理结束

要点

需要用优先队列存放已经分配的畜栏,并使得结束时间最早的畜栏始终位于队列头部。

#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
struct Cow {//奶牛
    int a, b; //挤奶区间起终点
    int No; //编号
    bool operator<(const Cow& c) const {
        return a < c.a;//按照开始时间从早到晚排序
    }
} cows[50100];
int pos[50100]; //pos[i]表示编号为i的奶牛去的畜栏编号
struct Stall {//畜栏
    int end; //结束时间
    int No; //编号
    bool operator<(const Stall& s) const {
        return end > s.end;//按照畜栏的结束时间排序
    }
    Stall(int e, int n) :end(e), No(n) { }
};
int main()
{
    int n;
    cin>>n;
    for (int i = 0; i < n; ++i) {
        cin>>cows[i].a>>cows[i].b;
        cows[i].No = i;
    }
    sort(cows, cows + n);
    int total = 0;
    priority_queue<Stall> pq;//畜栏的队列
    for (int i = 0; i < n; ++i) {
        if (pq.empty()) {//如果畜栏为空的话,就是放入第一个畜栏
            ++total;
            pq.push(Stall(cows[i].b, total));//并且新开一个畜栏,以放入当前奶牛的结束时间为畜栏的结束时间
            pos[cows[i].No] = total;
        }
        else {
            Stall st = pq.top();//指向队列的顶端,即即将释放的畜栏
            if (st.end < cows[i].a) { //端点也不能重合////如果畜栏的结束时间早于奶牛的开始时间的话
                pq.pop();
                pos[cows[i].No] = st.No;
                pq.push(Stall(cows[i].b, st.No));
            }
            else { //对应 if( st.end < cows[i].a //畜栏的结束时间晚于奶牛的开始时间,即队列中没有可以释放的畜栏,就新开一个畜栏放入奶牛
                ++total;
                pq.push(Stall{cows[i].b,total });//畜栏结束时间设置为奶牛结束
                pos[cows[i].No] = total;
            }
        }
    }
    cout << total << endl;
    for (int i = 0; i < n; ++i)
        cout << pos[i] << endl;
    return 0;
}
发布了97 篇原创文章 · 获赞 208 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/weixin_45822638/article/details/105272109