任务内容
Description
The famous ACM (Advanced Computer Maker) Company has rented a floor of a building whose shape is in the following figure.
The floor has 200 rooms each on the north side and south side along the corridor. Recently the Company made a plan to reform its system. The reform includes moving a lot of tables between rooms. Because the corridor is narrow and all the tables are big, only one table can pass through the corridor. Some plan is needed to make the moving efficient. The manager figured out the following plan: Moving a table from a room to another room can be done within 10 minutes. When moving a table from room i to room j, the part of the corridor between the front of room i and the front of room j is used. So, during each 10 minutes, several moving between two rooms not sharing the same part of the corridor will be done simultaneously. To make it clear the manager illustrated the possible cases and impossible cases of simultaneous moving.
For each room, at most one table will be either moved in or moved out. Now, the manager seeks out a method to minimize the time to move all the tables. Your job is to write a program to solve the manager's problem.
Input
The input consists of T test cases. The number of test cases ) (T is given in the first line of the input. Each test case begins with a line containing an integer N , 1<= N <= 200 , that represents the number of tables to move. Each of the following N lines contains two positive integers s and t, representing that a table is to move from room number s to room number t (each room number appears at most once in the N lines). From the N+3-rd line, the remaining test cases are listed in the same manner as above.
Output
The output should contain the minimum time in minutes to complete the moving, one per line.
翻译:
著名的 ACM(高级计算机制造商)公司租用了一栋楼的某一层,该楼层的形状如下图所示。
沿着走廊,楼层在北侧和南侧各有 200 个房间。最近,该公司制定了一项系统改革计划。改革内容包括在房间之间搬运大量的桌子。由于走廊很窄,而且所有的桌子都很大,所以每次只能有一张桌子通过走廊。因此需要制定一些计划来使搬运工作更高效。经理想出了如下计划:将一张桌子从一个房间搬到另一个房间可以在 10 分钟内完成。当把一张桌子从房间 i 搬到房间 j 时,会用到房间 i 前面到房间 j 前面之间的那段走廊。所以,每 10 分钟内,可以同时进行几个在不共用同一段走廊的两个房间之间的搬运工作。为了清晰说明情况,经理列举了可以同时搬运和不能同时搬运的各种情况示例。
对于每个房间而言,最多只会有一张桌子搬进或搬出。现在,经理正在寻找一种能使搬运所有桌子所需时间最短的方法。你的任务就是编写一个程序来解决经理所面临的这个问题。
输入
输入包含 T 个测试用例。测试用例的数量 T 在输入的第一行给出。每个测试用例的第一行包含一个整数 N(1 <= N <= 200),它代表要搬运的桌子数量。接下来的 N 行中,每行包含两个正整数 s 和 t,表示要将一张桌子从房间编号 s 搬到房间编号 t(每个房间编号在这 N 行中最多出现一次)。从第 N + 3 行起,其余的测试用例将按照上述相同的方式列出。
输出
输出应包含完成所有桌子搬运工作所需的最少时间(以分钟为单位),每行输出一个结果。
主要实现思路
- 整体思路概述 :
- 本题的核心任务是针对 ACM 公司在楼层中移动桌子的场景,给定多组桌子移动的起始房间和目标房间信息,要找出一种方案使得完成所有桌子移动所需的时间最少。由于走廊狭窄,同一走廊区间同时只能有一张桌子移动,程序通过对每个房间对应的走廊区间进行覆盖次数统计,找到被覆盖次数最多的区间,其覆盖次数乘以 10(可能代表每次移动一张桌子经过一个区间需要 10 分钟)就是完成所有桌子移动的最少时间。
- 输入与初始化部分 :
- 首先定义了多个变量,包括用于存储测试用例数量的
t
、每组测试用例中桌子移动数量的n
等,以及一个足够大的整型数组book
用于记录区间被覆盖的次数。通过scanf
函数读取测试用例的数量t
,然后进入外层while
循环处理每个测试用例。在每个测试用例开始时,使用memset
函数将book
数组所有元素初始化为 0,确保每个区间的覆盖次数初始状态是未被覆盖(为 0 次),接着读取当前测试用例中要移动桌子的数量n
。
- 首先定义了多个变量,包括用于存储测试用例数量的
- 处理每组桌子移动信息部分(核心逻辑) :
- 内层
for
循环针对每组要移动的桌子(循环n
次),先读取表示桌子移动起始房间号a
和目标房间号b
。为了统一处理,若a
大于b
,则交换它们的值,保证a
始终小于等于b
。 - 接着通过特定的计算方式(
a1 = (a + 1) / 2
和b1 = (b + 1) / 2
)将房间号转换为对应的走廊区间表示(根据题目给定的房间与走廊区间对应逻辑),确定了桌子移动所涉及的走廊区间范围。 - 然后再通过一个内层
for
循环,遍历从区间起始位置a1
到区间结束位置b1
的所有区间位置,将对应的book
数组元素值加 1,表示这些区间被覆盖了一次(意味着有桌子移动经过这些区间对应的走廊部分),通过这样的方式统计了每个区间被桌子移动覆盖的次数。
- 内层
- 查找最大覆盖次数及输出结果部分 :
- 在处理完当前测试用例中所有桌子移动信息后,先将变量
max
初始化为 0,用于记录区间覆盖次数的最大值。然后通过一个for
循环遍历book
数组(从第 1 个元素到第 220 个元素,这是根据题目可能涉及的区间范围设定的合理遍历范围),在循环过程中,如果发现当前数组元素值大于已记录的max
值,就更新max
为当前元素的值,以此找到覆盖次数最多的区间对应的覆盖次数。 - 最后按照题目要求的输出格式,输出覆盖次数最多的区间的覆盖次数乘以 10 的结果,这个结果可能代表完成所有桌子移动所需的最少时间,完成当前测试用例的处理,继续处理下一个测试用例(回到外层
while
循环,t--
继续下一轮循环),直到所有测试用例都处理完毕。
- 在处理完当前测试用例中所有桌子移动信息后,先将变量
cpp
#include<stdio.h>
#include<string.h>
int main()
{
int t, n, i, j, a, b, a1, b1, max, h; // 定义多个整型变量,t用于存储测试用例的数量,n用于存储每组测试用例中要移动桌子的数量,i、j用于循环计数,a、b用于读取输入的房间号,a1、b1用于计算调整后的房间号范围,max用于记录覆盖次数的最大值,h用于交换两个数时的临时存储
int book[1010]; // 定义一个整型数组book,用于记录每个区间被覆盖的次数,这里数组大小设为1010(根据实际逻辑需求设定的合适大小)
// 读取测试用例的数量t
scanf("%d", &t);
// 外层while循环,针对每个测试用例进行处理,每处理完一个测试用例,t减1,直到所有测试用例都处理完
while (t--)
{
// 使用memset函数将book数组的所有元素初始化为0,为当前测试用例的处理做准备,确保每个区间的覆盖次数初始为0
memset(book, 0, sizeof(book));
// 读取当前测试用例中要移动桌子的数量n
scanf("%d", &n);
// 内层for循环,用于读取每组要移动桌子的相关房间号信息,并进行相应处理,循环n次,对应n组数据
for (i = 1; i <= n; i++)
{
// 读取表示桌子移动起始房间号a和目标房间号b
scanf("%d%d", &a, &b);
// 如果起始房间号a大于目标房间号b,交换它们的值,确保a始终小于等于b,方便后续统一处理
if (a > b)
{
h = a;
a = b;
b = h;
}
// 计算起始房间号对应的区间起始位置a1,这里通过 (a + 1) / 2 来转换,将房间号转换为对应的区间表示(根据题目特定的逻辑,具体与走廊区间划分相关)
a1 = (a + 1) / 2;
// 计算目标房间号对应的区间结束位置b1,同样通过 (b + 1) / 2 来转换,确定对应的区间范围
b1 = (b + 1) / 2;
// 内层循环,遍历从区间起始位置a1到区间结束位置b1的所有区间位置,将对应的book数组元素值加1,表示这些区间被覆盖了一次(意味着有桌子移动经过这些区间对应的走廊部分)
for (j = a1; j <= b1; j++)
{
book[j]++;
}
}
max = 0; // 初始化最大值max为0,用于后续查找book数组中覆盖次数的最大值
// 遍历book数组,从第1个元素到第220个元素(根据题目可能涉及的区间范围设定的遍历范围),查找覆盖次数的最大值
for (i = 1; i <= 220; i++)
{
if (book[i] > max) // 如果当前元素值大于已记录的最大值max
max = book[i]; // 更新最大值max为当前元素的值
}
// 输出覆盖次数最多的区间的覆盖次数乘以10的结果,可能代表完成所有桌子移动所需的最少时间(根据题目逻辑要求的输出格式)
printf("%d\n", max * 10);
}
return 0;
}