UVa 1000 Airport Configuration
题目描述
ACM Airlines\texttt{ACM Airlines}ACM Airlines 航空公司以 von Neumann\texttt{von Neumann}von Neumann 机场作为枢纽机场。该机场采用走廊式布局:到达登机口均匀排列在走廊北侧,出发登机口均匀排列在走廊南侧。相邻两个登机口的距离等于走廊的宽度。每个到达登机口和出发登机口都唯一分配给一个城市。
中转乘客从出发城市的到达登机口进入航站楼,然后前往目的城市的出发登机口转机。由于机场内有商店和花园,不能斜穿走廊,因此从到达登机口 GiG_iGi 到出发登机口 GjG_jGj 的距离为 ∣i−j∣+1|i - j| + 1∣i−j∣+1。
人流负荷定义为:乘客人数 × 到达口与出发口之间的距离。总人流负荷为所有出发城市到目的城市的人流负荷之和。
输入包含多个测试用例,每个测试用例给出城市间的乘客流量数据,以及若干种登机口分配方案(配置)。需要计算每种配置的总人流负荷,并按负荷升序输出配置编号和负荷,负荷相同时配置编号小的优先。
题目分析
关键点解析
-
距离计算
题目的图中示例:到达口 G1G1G1(索引 000)到出发口 G3G3G3(索引 222)的距离为 1+2=31 + 2 = 31+2=3。
这个距离由两部分组成:- 水平方向:从 G1G1G1 走到 G3G3G3 正下方对应的出发口,需要经过 ∣0−2∣=2|0 - 2| = 2∣0−2∣=2 个间隔。
- 垂直方向:从北侧到达口走到南侧出发口,需要横穿走廊,距离为 111。
因此距离公式为 ∣i−j∣+1|i - j| + 1∣i−j∣+1。
-
输入格式的特殊性
交通数据部分:每行开头有一个整数 1…N1 \dots N1…N,显式标识该行数据对应的出发城市编号。虽然输入通常按顺序给出,但题目规范要求必须读取该编号,不能依赖循环变量隐式确定。 -
配置数量
每个测试用例最多有 202020 个配置,N≤25N \leq 25N≤25,因此直接模拟计算即可,无需优化。 -
输出排序
按总负荷升序排序,负荷相同按配置编号升序。输出时配置编号右对齐宽度为 555,负荷左对齐。
解题思路
步骤 1:读取交通数据
- 读入整数 NNN,若为 000 则结束整个程序。
- 创建大小为 (N+1)×(N+1)(N+1) \times (N+1)(N+1)×(N+1) 的乘客矩阵
passenger,使用 111 基索引。 - 循环 NNN 次(每行对应一个城市):
- 读入
from(出发城市编号)。 - 读入
k(目的城市数量)。 - 循环 kkk 次,读入
to和cnt,存入passenger[from][to] = cnt。
- 读入
步骤 2:读取并处理每个配置
配置部分以单独一行 000 结束。每个配置包含三行:
- 配置编号
configId(正整数)。 - NNN 个整数,表示到达口分配(第 iii 个位置的城市编号)。
- NNN 个整数,表示出发口分配(第 jjj 个位置的城市编号)。
对于每个配置:
- 建立映射
arrPos[city]:城市 citycitycity 所在的到达口索引(000 基)。 - 建立映射
depPos[city]:城市 citycitycity 所在的出发口索引(000 基)。 - 双重循环遍历所有城市对 (from,to)(from, to)(from,to):
- 若
passenger[from][to] > 0,则计算距离 dist=∣arrPos[from]−depPos[to]∣+1\text{dist} = |\text{arrPos}[from] - \text{depPos}[to]| + 1dist=∣arrPos[from]−depPos[to]∣+1。 - 累加负荷:
totalLoad += passenger[from][to] * dist。
- 若
- 将
(configId, totalLoad)存入结构体数组。
步骤 3:排序与输出
- 使用自定义比较函数:先按
load升序,再按id升序。 - 调用
std::sort。 - 输出表头
"Configuration Load"。 - 遍历排序后的结果,按格式
printf("%5d %d\n", id, load)输出。
复杂度分析
- 每个配置的计算复杂度为 O(N2)O(N^2)O(N2),N≤25N \leq 25N≤25,配置数 ≤20\leq 20≤20,因此单测试用例最多约 20×252=1250020 \times 25^2 = 1250020×252=12500 次操作,非常快。
- 空间复杂度 O(N2)O(N^2)O(N2)。
注意事项
- 输入读取顺序:交通数据每行开头的
from必须显式读取,不可省略。 - 距离公式:∣i−j∣+1|i - j| + 1∣i−j∣+1,不要误用为 ∣i−j∣|i - j|∣i−j∣。
- 多测试用例:每处理完一个测试用例,要清空配置列表,重新读取下一个。
- 输出格式:配置编号右对齐 555 位,负荷左对齐(直接
%d即可),中间一个空格。
代码实现
// Airport Configuration
// UVa ID: 1000
// Verdict: Accepted
// Submission Date: 2026-04-26
// UVa Run Time: 0.000s
//
// 版权所有(C)2026,邱秋。metaphysis # yeah dot net
#include <bits/stdc++.h>
using namespace std;
struct Config {
int id;
int load;
};
bool cmp(const Config& a, const Config& b) {
if (a.load != b.load) return a.load < b.load;
return a.id < b.id;
}
int main() {
int N;
while (cin >> N && N != 0) {
// 乘客矩阵
vector<vector<int>> passenger(N + 1, vector<int>(N + 1, 0));
for (int i = 1; i <= N; i++) {
int from;
cin >> from;
int k; cin >> k;
for (int t = 0; t < k; t++) {
int to, cnt; cin >> to >> cnt;
passenger[from][to] = cnt;
}
}
vector<Config> configs;
int configId;
while (cin >> configId && configId != 0) {
vector<int> arrPerm(N), depPerm(N);
for (int i = 0; i < N; i++) cin >> arrPerm[i];
for (int i = 0; i < N; i++) cin >> depPerm[i];
// 映射城市 -> 到达口索引
vector<int> arrPos(N + 1);
for (int i = 0; i < N; i++) arrPos[arrPerm[i]] = i;
// 映射城市 -> 出发口索引
vector<int> depPos(N + 1);
for (int i = 0; i < N; i++) depPos[depPerm[i]] = i;
int totalLoad = 0;
for (int from = 1; from <= N; from++) {
for (int to = 1; to <= N; to++) {
int cnt = passenger[from][to];
if (cnt > 0) {
int dist = abs(arrPos[from] - depPos[to]) + 1;
totalLoad += cnt * dist;
}
}
}
configs.push_back({configId, totalLoad});
}
sort(configs.begin(), configs.end(), cmp);
cout << "Configuration Load\n";
for (const auto& cfg : configs) {
printf("%5d %d\n", cfg.id, cfg.load);
}
}
return 0;
}
总结
本题的核心在于正确理解距离计算公式,并严格按照输入格式要求读取数据。由于数据规模较小,可以直接模拟计算每种配置的总负荷,再排序输出。代码实现时需要注意:
- 显式读取每行开头的城市编号。
- 建立从城市到登机口索引的映射,以便 O(1)O(1)O(1) 查找位置。
- 输出格式的右对齐控制。
掌握这些细节后,本题即可顺利通过。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)