📜  门|门CS 2011 |第 60 题(1)

📅  最后修改于: 2023-12-03 15:28:48.972000             🧑  作者: Mango

题目介绍

这道题目是ACM/ICPC门户网站上的一道经典题目,也是很多程序员在学习数据结构和算法时的必做题之一。题目难度中等,需要一定的编程基础和思维能力。

题目描述

有n个人排队进门,门口有m个刷卡机。第i个人需要花费ti时间刷卡,且必须在pi时刻之前刷卡。问n个人都能够在规定的时间内刷卡吗?如果可以,请给出一种刷卡方案;如果不能,请输出-1。

输入格式

输入共n+1行,第1行包含两个整数n,m,表示排队的人数和刷卡机的数量。 接下来的n行,每行包含两个整数ti,pi,表示第i个人的刷卡所需的时间和最晚刷卡时间。

输出格式

如果所有人都能够成功刷卡,输出每个人开始刷卡的时间; 如果有人无法成功刷卡,输出-1。

输入样例
5 2
1 2
2 7
3 3
4 9
5 6
输出样例
0 2
1 7
2 3
4 9
4 10

解题思路

这道题目属于贪心算法的范畴,我们可以通过合理地规划刷卡顺序来使得所有人都能够顺利刷卡。

首先,我们对所有人按照最晚刷卡时间p从小到大进行排序,这样可以保证我们先处理最紧急的情况。然后,对于每个人,我们在所有可用的刷卡机中选择花费时间最小的机器进行刷卡,并记录下该机器的使用时间。最后,我们再检查一遍所有人的刷卡时间是否均没有超过各自的最晚刷卡时间,如果存在超时的情况,则说明无法全部刷卡,返回-1即可。

代码片段

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 1010;

struct person {
    int id, t, p;

    bool operator< (const person &W)const {
        return p < W.p;
    }
}persons[N];

int n, m;
int machine[N];

int main() {
    cin >> n >> m;
    for(int i = 1; i <= n; i ++) {
        persons[i].id = i;
        cin >> persons[i].t >> persons[i].p;
    }

    sort(persons + 1, persons + n + 1);

    bool flag = true;
    for(int i = 1; i <= n; i ++) {
        int j = 1;
        for(; j <= m; j ++) {
            if(machine[j] <= persons[i].p) break;
        }
        if(j > m) {
            flag = false;
            break;
        }
        machine[j] = persons[i].p + persons[i].t;
        printf("%d %d\n", persons[i].id - 1, machine[j] - persons[i].t);
    }

    if(!flag) puts("-1");
    return 0;
}

以上是C++代码片段,完整代码可以参考门|门CS 2011 |第 60 题