目录
玩石子游戏获得最大得分:贪心策略深度解析(Leetcode 1753)
玩石子游戏获得最大得分:贪心策略深度解析(Leetcode 1753)
在本篇文章中,我们将深入探讨一个非常有意思的单人游戏问题,考察我们对贪心算法和问题建模能力的掌握。这个题目常见于算法练习平台 Leetcode,编号为 1753. Maximum Score From Removing Stones,但我们在本文将用自己的语言和逻辑对其进行完整剖析。
🧩 题目描述
你正在玩一个单人游戏,面前有三堆石子,它们的数量分别为 a、b 和 c。
游戏规则如下:
- 每回合,你必须从两个不同的非空堆中各取出一颗石子。
- 每进行一回合,你的得分就增加 1。
- 当存在两个或更多堆为空时,游戏结束。
你的目标是:求出最多可以获得多少分?
🧠 解题分析
本题看起来像是一个模拟题,但我们若尝试逐步模拟,会发现状态非常多。更好的思路是找到一种 数学建模 + 贪心策略 来简化整个过程。
首先观察:
- 每次操作会从两个堆中各取一个石子。也就是说,每次操作消耗 2 个石子,获得 1 分。
- 游戏结束的条件是有两个或以上的堆为空。
那就有两个思考方向:
情况一:石子总数是偶数 or 奇数?
石子总数为 a + b + c,我们最多只能进行 (a + b + c) // 2 次操作,因为每次都要取两颗石子。
所以,理论最大得分是:
max_score <= (a + b + c) // 2
情况二:一堆的石子远多于其他两堆?
如果某一堆,比如说 c 非常大,大到 c > a + b,那么游戏会提前结束:
- 因为你不能从两个空堆中取石子。
- 所以,当
a + b的石子都用光时,游戏也就结束了。 - 所以在这种极端情况下,最大得分是
a + b。
因此,我们得出一个统一的公式来应对所有情况:
min(total_sum // 2, total_sum - max_value)
其中:
total_sum = a + b + cmax_value = max(a, b, c)
🛠 解题方法(Python 实现)
class Solution:
def maximumScore(self, a: int, b: int, c: int) -> int:
total = a + b + c
max_val = max(a, b, c)
return min(total - max_val, total // 2)
这个实现非常简洁,仅需一行主逻辑:
- 计算总石子数
- 找出最大堆
- 返回上述公式的最小值
🧮 示例说明
示例 1:
输入: a = 2, b = 4, c = 6
总和: 12, 最大值: 6
最大得分 = min(12 - 6, 12 // 2) = min(6, 6) = 6
你可以进行 6 次操作,每次取两个堆中的一个石子。
示例 2:
输入: a = 4, b = 4, c = 6
总和: 14, 最大值: 6
最大得分 = min(14 - 6, 14 // 2) = min(8, 7) = 7
虽然剩余两个堆的数量加起来大于最大堆,但由于总数是 14,只能做 7 次操作(最多使用 14 颗石子,每次两个)。
示例 3:
输入: a = 1, b = 8, c = 8
总和: 17, 最大值: 8
最大得分 = min(17 - 8, 17 // 2) = min(9, 8) = 8
最大堆与其他两个堆加起来很接近,但得分仍然受限于总石子数量除以 2。
⏱ 复杂度分析
- 时间复杂度:
O(1)
只做了几次基本运算,没有循环或递归。 - 空间复杂度:
O(1)
只使用了常数个变量。
这也是本题的优势之一——解法极度简洁。
🔍 贪心策略对比暴力解法
| 方法 | 思想 | 时间复杂度 | 可行性 |
| 暴力模拟 | 每次尝试不同的取法 | 高(指数级) | 不可行 |
| 贪心策略(本题) | 数学推导 + 最小上限限制 | 常数级 | ✅ 推荐 |
🧾 总结
本题虽然看似简单,但关键在于抽象游戏过程中的数学模型。你需要注意以下几点:
- 每次操作都耗费两个石子,得 1 分,所以得分最多不会超过总石子数除以 2。
- 如果最大那一堆石子远远多于其他两堆,那么游戏会提早结束,得分最多为其他两堆之和。
- 最终答案是两种上限的较小者。
最终公式:
min((a + b + c) // 2, a + b + c - max(a, b, c))
318

被折叠的 条评论
为什么被折叠?



