📜  QA – 安置测验| SP 大赛 2 |问题 8(1)

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

QA – 安置测验| SP 大赛 2 |问题 8

这是一道SP大赛2的问题,需要做的是编写一个程序,解决关于安置测验的问题。

题目描述

有n个房间,每个房间里都有一个学生。现在需要将这n个学生按照给定的顺序进行安置,规则如下:

  1. 每个房间只能安置一个学生,且一个学生只能安置在一个房间里。

  2. 安置时需要满足以下条件:

    • 如果第i个学生和第i+1个学生之间相差k个位置,则这两个学生应当被安置在距离k个房间的位置上。

    • 如果i+1>n,则不需要考虑第i+1个学生和第i个学生之间的距离。

  3. 如果存在多种满足条件的安置方法,则输出其中字典序最小的那种方案。

输入格式

第一行两个整数n,k,表示学生数量和学生之间最大允许差距。

第二行n个整数p1,p2,…,pn,表示学生原来应当在的位置。

输出格式

输出n个整数,表示最终的安置方案。

示例

输入:

5 2
4 0 0 4 4

输出:

4 2 0 3 1
说明

下面对输入样例进行解释:

  1. 有5个学生,他们原来应当在位置4,1,2,4,5上。

  2. 学生之间最大允许差距为2。

  3. 最终的安置顺序为:第一个学生在位置4上,接着安置第四个学生在位置3上,然后安置第二个学生在位置2上,接着安置第五个学生在位置1上,最后安置第三个学生在位置0上。

代码实现
### 解题思路

本题需要按照给定的顺序安置学生,并满足一定条件。因此,我们可以使用贪心算法来解决这一问题。

具体思路如下:

1. 对于每个学生,我们从其原本应当所在位置开始寻找可以安置的位置。

2. 需要满足的条件有两个:一是和前一个学生的位置相差k个位置,二是选取的是字典序最小的可行位置。

3. 如果当前可行位置和上一个学生的位置相差k个位置,则直接安置在当前位置上;否则,我们从上一个学生的位置开始往后搜索位置。如果找不到一个可行位置,则寻找离当前可行位置最近的可行位置,并安置在该位置。

### 代码实现

```python
n, k = map(int, input().split())
pos = list(map(int, input().split()))

ans = [0] * n
used = [False] * (n + 1)

for i in range(n):
    p = pos[i]  # 第i个学生原本应当在的位置
    available = []  # 可行位置列表

    # 遍历p到p+k范围内的位置,加入可行位置列表中
    for j in range(max(1, p - k), min(n, p + k + 1)):
        if not used[j]:
            available.append(j)

    # 如果可行位置列表非空,则选取字典序最小的位置
    if available:
        available.sort()
        ans[i] = available[0]
        used[ans[i]] = True
    else:
        # 否则寻找离当前可行位置最近的可行位置
        for j in range(p + k, p - k - 1, -1):
            if 1 <= j <= n and not used[j]:
                ans[i] = j
                used[ans[i]] = True
                break

print(*ans)
时间复杂度

本题使用贪心算法,时间复杂度为O(n^2)。在极端情况下(即k=n),时间复杂度为O(n^3)。