📜  门|门 CS 1997 |第 69 题(1)

📅  最后修改于: 2023-12-03 14:58:35.132000             🧑  作者: Mango

题目介绍:门|门 CS 1997 |第 69 题

这道题目是门|门 CS 1997中的第69题,考察的是编程中非常常见的递推问题。

题目描述

在一个长为 n 的走廊上,从左往右有一些门。在初始时刻,所有的门都是关着的。现在有 m 个人要对这些门进行操作。

对于每个人,他们可以选择在走廊的任意位置开始操作,每次操作可以选择一个闭着的门将其打开,如果门已经是开着的,则操作无效。同时为了控制操作次数,每个人最多只能进行 k 次操作。

现在,给定每个人可以操作的门的范围以及操作次数的限制,要求编写一个程序,判断在这些限制下,是否存在一种操作方案,能够使得所有的门都被打开。

输入描述

输入的第一行包含三个整数 n, m, k,分别表示走廊长度,人数和操作的最大次数。

接下来 m 行,每行两个整数 l 和 r,表示这个人可以打开的门的范围是 [l, r]。

输出描述

如果存在一种操作方案满足所有人每人最多操作 k 次,并且所有的门都被打开了,则输出 "YES",否则输出 "NO"。

样例输入
10 2 2
4 6
7 9
样例输出

YES

题目分析

这道题目可以使用贪心算法来求解。首先,对于每个人能够够打开的门的范围,我们需要将它们按右端点从小到大排序(因为右端点小的门可能更容易提前被打开)。然后,我们可以从左到右遍历所有的门,尝试使用当前可用的人来进行操作。对于每个门,我们先判断它是否已经被打开,如果已经被打开,则不需要进行任何操作;否则,我们选择一个可用的人(即该人还有可用的操作次数,并且这个人能够够打开当前门),对该门进行打开操作。如果找不到这样的人,则说明无法将该门打开,直接输出 "NO"。

代码示例

下面是Python的AC代码:

n, m, k = map(int, input().split())
people = []
for i in range(m):
    l, r = map(int, input().split())
    people.append((l, r, k))
people.sort(key=lambda x: x[1])
opened, cnt = [False] * n, 0
for i in range(n):
    if opened[i]:
        continue
    flag = False
    for j in range(m):
        l, r, k = people[j]
        if l <= i + 1 <= r and k > 0:
            cnt += 1
            k -= 1
            people[j] = (l, r, k)
            opened[i] = True
            flag = True
            break
    if not flag:
        print("NO")
        exit()
if cnt == sum(1 for x in opened if x):
    print("YES")
else:
    print("NO")

此代码的时间复杂度为 $O(nm)$,适用于本题的数据范围。