问题重述 我们有国王和 n 位大臣,每个人左手和右手各写一个整数。国王站在队伍的最前面,大臣们排成一排。每位大臣获得的金币数是:排在他前面的所有人(包括国王)左手上的数的乘积,除以他自己右手上的数,然后向下取整。我们需要重新排列大臣的顺序,使得获得最多金币的大臣的金币数尽可能少。 输入格式 - 第一行:n(大臣人数) - 第二行:a b(国王左手的数和右手的数) - 接下来 n 行:每行 a_i b_i(第 i 位大臣左手的数和右手的数) 输出格式 重新排列后,获得最多金币的大臣的金币数。 示例分析 输入: ``` 3 1 1 2 3 7 4 4 6 ``` 输出: ``` 2 ``` 解题思路 这是一个典型的贪心算法问题。我们需要找到一种排序方式,使得按照这种顺序排列后,最大的金币数最小。 关键观察 假设有两个大臣 i 和 j,我们需要决定他们的顺序。设国王的左手数为 a0,i 的左手数为 a_i,右手数为 b_i;j 的左手数为 a_j,右手数为 b_j。 如果 i 在前,j 在后: - i 的金币:a0 / b_i - j 的金币:a0 * a_i / b_j 如果 j 在前,i 在后: - j 的金币:a0 / b_j - i 的金币:a0 * a_j / b_i 我们希望最大值尽可能小,因此需要比较 max(a0 / b_i, a0 * a_i / b_j) 和 max(a0 / b_j, a0 * a_j / b_i),选择较小的那个。 简化比较: 比较 a_i * b_i 和 a_j * b_j。如果 a_i * b_i < a_j * b_j,则 i 应该排在 j 前面。 贪心策略 按照 a_i * b_i 从小到大排序大臣的顺序。这样排列后,计算每个大臣的金币数,并找出最大值。 解决代码 ```python n = int(input()) king_a, king_b = map(int, input().split()) ministers = [] for _ in range(n): a, b = map(int, input().split()) ministers.append((a, b)) # 按照 a * b 从小到大排序 ministers.sort(key=lambda x: x[0] * x[1]) max_reward = 0 product = king_a # 前面所有人的左手数的乘积,初始是国王的左手数 for a, b in ministers: reward = product // b if reward > max_reward: max_reward = reward product *= a print(max_reward) ``` 代码解释 1. 读取输入:n(大臣人数),国王的左右手数,以及各位大臣的左右手数。 2. 对大臣按照 a_i * b_i 从小到大排序。 3. 初始化最大金币数为 0,左手数乘积为国王的左手数。 4. 遍历排序后的大臣: - 计算当前大臣的金币数:product // b。 - 更新最大金币数。 - 更新左手数乘积:product *= a。 5. 输出最大金币数。 示例验证 输入: ``` 3 1 1 2 3 7 4 4 6 ``` 排序后的大臣顺序: - (2, 3): 2*3=6 - (4, 6): 4*6=24 - (7, 4): 7*4=28 计算: 1. product = 1 - (2,3): reward = 1 // 3 = 0; product = 1 * 2 = 2 - (4,6): reward = 2 // 6 = 0; product = 2 * 4 = 8 - (7,4): reward = 8 // 4 = 2; product = 8 * 7 = 56 - max_reward = max(0, 0, 2) = 2 输出:2,与示例一致。 复杂度分析 - 排序:O(n log n) - 遍历计算:O(n) - 总复杂度:O(n log n) 通过贪心算法,按照 a_i * b_i 从小到大排序大臣的顺序,可以使得最大金币数最小化。该策略的正确性基于局部最优的选择能够导致全局最优解。 [2025-05-10 20:58:15 | AI问答 | 1002点数解答]