POJ-3190 Stall Reservations 解题报告

POJ - 3190

题目描述

Stall Reservations

Oh those picky N (1 <= N <= 50,000) cows! They are so picky that each one will only be milked over some precise time interval A..B (1 <= A <= B <= 1,000,000), which includes both times A and B. Obviously, FJ must create a reservation system to determine which stall each cow can be assigned for her milking time. Of course, no cow will share such a private moment with other cows.
Help FJ by determining:
·The minimum number of stalls required in the barn so that each cow can have her private milking period
·An assignment of cows to these stalls over time
Many answers are correct for each test dataset; a program will grade your answer.

Input

Line 1: A single integer, N
Lines 2..N+1: Line i+1 describes cow i’s milking interval with two space-separated integers.

Output

Line 1: The minimum number of stalls the barn must have.
Lines 2..N+1: Line i+1 describes the stall to which cow i will be assigned for her milking period.

Sample Input

5
1 10
2 4
3 6
5 8
4 7

Sample Output

4
1
2
3
2
4

Hint

Explanation of the sample:
Here’s a graphical schedule for this output:
Time 1 2 3 4 5 6 7 8 9 10
Stall1 c1>>>>>>>>>>>>>>>>>>>>>>>>>>>
Stall2 .. c2>>>>>> c4>>>>>>>>> .. ..
Stall3 .. .. c3>>>>>>>>> .. .. .. ..
Stall4 .. .. .. c5>>>>>>>>> .. .. ..
Other outputs using the same number of stalls are possible.

题目大意

现在要为N头奶牛分配畜栏,目的就是求解这个最少的畜栏数,并打印每个奶牛所在的畜栏编号。其中,每头奶牛开始的时间A和结束的时间B确定,在最开始,没有畜栏。
奶牛数N满足1 <= N <= 50,000,每头牛的开始时间和结束时间A, B满足1 <= A <= B <= 1,000,000。

解题方法

题目的基本方向是贪心。即找出开始时间最早的奶牛,为它找结束时间最早的畜栏。若这样的畜栏存在,即

  • 畜栏的结束时间 < 奶牛的开始时间

则将这头奶牛放入这个畜栏,并将畜栏的结束时间修改为奶牛的结束时间。若不存在这样的畜栏,即

  • 结束时间最小的畜栏的结束时间 > 奶牛的开始时间

则新增加一个畜栏,将它的结束时间修改为奶牛的结束时间。
我们建立两个结构体来分别表示奶牛和畜栏

  • 奶牛结构体:包含一个奶牛的编号,开始时间和结束时间,和 < 号重载
  • 畜栏结构体:包含畜栏的编号,结束时间,和 < 号重载(这里为什么要重载在后面说)

在这个算法中我们会遇到这个几个问题:

  1. 如何寻找开始时间最早的奶牛,即当前最先要安排的奶牛。
  2. 如何寻找结束时间最早的畜栏

对于问题1,我们使用algorithm头文件中的sort函数,按照奶牛的开始时间进行排序,这时候就要用到之前提到的运算符重载,重载 < 号之后就可以直接对结构体进行排序。
而对于畜栏,我们不可能没分配一只奶牛就排序一次,这样复杂度会达到O(n²),会超时。在这里我们要用到queue头文件中的priority_queue(优先级队列)这个数据结构。
(关于优先级队列可参考此博客:https://blog.csdn.net/c20182030/article/details/70757660
因此队头元素,都是这个队列中最大的元素。因此,重载 < 号,使它返回具有最小的结束时间的畜栏。这样,就解决了以上提出的两个问题。

代码如下

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#define MAX 50000
using namespace std;
struct Cow
{
    int No;
    int begin;
    int end;
    bool operator < (const Cow &c) const
    {
        return begin < c.begin;
    }
}cow[MAX];
struct Stall
{
    int No;
    int end;
    bool operator < (const Stall &s) const
    {
        return end > s.end;
    }
    Stall(int n, int e) : No(n), end(e) {}
};
int N;
priority_queue<Stall> pq;
int pos[MAX];
int main()
{
    scanf("%d", &N);
    int account = 0;
    for(int i = 0; i < N; i ++)
    {
        scanf("%d%d", &cow[i].begin, &cow[i].end);
        cow[i].No = i;
    }
    sort(cow, cow + N);
    pq.push(Stall(++account, 0));
    for(int i = 0; i < N; i ++)
    {
        if(cow[i].begin > pq.top().end)
        {
            Stall tem = pq.top();
            pq.pop();
            pq.push(Stall(tem.No, cow[i].end));
            pos[cow[i].No] = tem.No;
        }
        else
        {
            pq.push(Stall(++account, cow[i].end));
            pos[cow[i].No] = account;
        }
    }
    printf("%d\n", account);
    for(int i = 0; i < N; i ++)
        printf("%d\n", pos[i]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41480330/article/details/82467589