ML0001 团建
时间限制:1秒 占用内存:64M
小码弟在参加班级团建。
班里有𝑛个人,现在在池塘边围了一个圈。同学们的学号按顺时针依次为 a1,a2,…,an,保证 𝑎𝑖ai 互不相同。对于 1≤𝑖<𝑛,学号为 𝑎𝑖和 𝑎𝑖+1 的同学是相邻的,特别地 𝑎1与 𝑎𝑛 也相邻。我们定义相邻两人的距离都为 1。
接下来的活动需要他们按学号大小排好队。定义一个队伍是好的,当且仅当从学号最小的同学开始,在顺时针方向上学号递增排列。如 (5,6,1,2,3,4)是好的,而 (5,1,2,4,3,6) 是不好的。
同学们都想尽量在排队的时候少走路。所以小码弟提议一名同学待在原地,其它同学分别前往应去的位置。由于在原地的同学可能高兴的手舞足蹈,所以其它同学走动时不能经过他。
请你告诉小码弟应该选择哪名同学待在原地不动,使其余同学走过路程之和最小。
格式
输入格式:
- 第一行一个整数𝑛(𝑛≤1000),代表班级人数。
- 第二行输入𝑛个整数𝑎1,𝑎2,…,𝑎𝑛(0≤𝑎𝑖≤109),第 𝑖个数代表第 𝑖个同学的学号。
输出格式:
- 输出一行一个整数,为路程和的最小值。
题目理解:
我们需要将围成一个圈的同学们按照学号顺序排好队,且要找出一种方式使得在排队的过程中,除了一个同学原地不动外,其余同学走过的路程和最小。并且,要求队伍必须是顺时针方向上学号递增排列。
解题思路
-
确定起始位置:
- 队伍需要从学号最小的同学开始顺时针递增排列,所以我们首先需要找到学号最小的同学的位置。
-
判断起始位置的可行性:
- 找到最小学号的位置后,以该位置作为起始点,顺时针检查学号是否递增。
-
计算每种方案的路程和:
- 对于每一个可能的起始点,我们需要计算在该点保持不动的情况下,其他同学移动的总距离。
- 由于不能经过原地不动的同学,我们需要考虑到每个同学的实际行走路径。
-
遍历所有起始点并比较:
- 检查所有可能的起始点,计算每种情况下的总移动距离,并选择最小的一个。
算法思想:
该代码通过模拟每个学生作为原地不动的情况,并计算其他学生的最小移动距离,从而找到总移动距离最小的方案。这样可以确保同学们尽量少走路。
代码步骤:
-
读取输入:
- 使用
read
函数读取输入数据。 read
函数返回一个迭代器,用于读取输入的整数。
- 使用
-
数据处理:
- 使用
sorted
和index
来对学号进行排名,转化为相对位置。 - 计算每个学生的排名。
- 使用
-
计算最小移动距离:
- 枚举每个学生作为原地不动的学生。
- 对于每个学生,计算其他学生移动的总距离。
-
输出结果:
- 输出最小移动距离。
代码1:(C++)
#include <bits/stdc++.h>
using namespace std;
template <typename F> inline void read(F &n) {
F w = 1; n = 0;
char ch = getchar();
while (!isdigit(ch) && ch != EOF) {
if(ch == '-') w = -1;
ch = getchar();
}
while (isdigit(ch) && ch != EOF) {
n = (n << 1) + (n << 3) + (ch & 15);
ch = getchar();
}
n *= w;
}
template <typename T, typename ...L> inline void read(T &n, L &...l) {
read(n);
read(l...);
}
template <typename T> inline void write(T n) {
if (n < 0) {
putchar('-');
n = -n;
}
if(n > 9) {
write(n / 10);
}
putchar('0' + n % 10);
}
template <typename T> inline void ckmax(T &x, T y) {
x = x > y ? x : y;
}
template <typename T> inline void ckmin(T &x, T y) {
x = x < y ? x : y;
}
typedef long long ll;
typedef unsigned long long ull;
const int N = 1005;
int n, a[N], hs[N];
int res = N * N;
int main() {
read(n);
for (int i = 0; i < n; ++i) {
read(a[i]);
hs[i] = a[i];
}
sort(hs, hs + n);
for (int i = 0; i < n; ++i) {
a[i] = lower_bound(hs, hs + n, a[i]) - hs;
}
for (int i = 0; i < n; ++i) {
int cnt = 0;
for (int j = 0; j < n; ++j) {
if (j != i) {
int x = j, y = (a[j] - a[i] + n + i) % n;
if (x > y) swap(x, y);
if (x < i && i < y) {
cnt += (x + n - y);
} else {
cnt += y - x;
}
}
}
ckmin(res, cnt);
}
printf("%d\n", res);
return 0;
}
代码2:(python)
def read():
return map(int, input().split())
def calculate_distance(start_idx, n, a):
cnt = 0
for j in range(n):
if j != start_idx:
x = j
y = (a[j] - a[start_idx] + n + start_idx) % n
if x > y:
x, y = y, x
if x < start_idx < y:
cnt += (x + n - y)
else:
cnt += y - x
return cnt
def find_minimum_total_distance(n, ids):
hs = sorted(ids)
a = [hs.index(id) for id in ids]
res = n * n
for i in range(n):
cnt = calculate_distance(i, n, a)
res = min(res, cnt)
return res
if __name__ == "__main__":
n, = read()
ids = list(read())
print(find_minimum_total_distance(n, ids))
两个代码均经过测评,成功通过。