这道题是经典的博弈论 + 动态规划问题。🧐 题目解析Alice 和 Bob 轮流从一排石子堆的开头拿走 1、2 或 3 堆石子。Alice 先手。每个玩家都想最大化自己的得分。我们需要判断在双方都采取最优策略的情况下,谁会获胜。💡 核心思路:动态规划这道题的关键在于如何定义状态。我们可以从“当前玩家相对于对手的领先优势”这个角度来思考。状态定义我们定义 dp[i] 为:当游戏从第 i 堆石子开始时,当前行动的玩家相对于另一位玩家能获得的最大分数差。- 如果 dp[i] 是正数,说明当前玩家能赢。- 如果 dp[i] 是负数,说明当前玩家会输。- 如果 dp[i] 是 0,说明会平局。状态转移当轮到当前玩家在位置 i 行动时,他有三种选择:拿 1 堆、2 堆或 3 堆。1. 拿 1 堆 (stoneValue[i]): * 当前玩家获得 stoneValue[i] 分。 * 游戏状态变为 i+1,轮到对手行动。 * 在 i+1 状态下,对手相对于当前玩家的优势是 dp[i+1]。 * 所以,当前玩家相对于对手的净优势是 stoneValue[i] - dp[i+1]。2. 拿 2 堆 (stoneValue[i] + stoneValue[i+1]): * 净优势是 (stoneValue[i] + stoneValue[i+1]) - dp[i+2]。3. 拿 3 堆 (stoneValue[i] + stoneValue[i+1] + stoneValue[i+2]): * 净优势是 (stoneValue[i] + stoneValue[i+1] + stoneValue[i+2]) - dp[i+3]。当前玩家会选择这三种方案中对自己最有利(即净优势最大)的一种。因此,状态转移方程为:dp[i] = max(拿1堆的收益, 拿2堆的收益, 拿3堆的收益)计算顺序和边界我们从后往前计算 dp 数组(从数组末尾到开头)。* 边界条件:当 i = n 时,没有石子可拿,dp[i] = 0。最终,我们只需要看 dp[0] 的值:* dp[0] 0:Alice 赢。* dp[0] = 0; i--) { // 初始化为一个很小的值 dp[i] = Integer.MIN_VALUE; int sum = 0; // 尝试拿 1, 2, 3