区间动态规划例题:预测赢家问题
字数 1237 2025-10-31 22:46:15
区间动态规划例题:预测赢家问题
题目描述
给定一个非负整数数组 nums,两名玩家轮流从数组的两端(即第一个或最后一个元素)取数,每次取一个数字,取走后数字被移除。玩家每次只能取两端的数字,不能取中间的数字。最终取的数字总和最多的玩家获胜。假设两名玩家都采取最优策略,判断先手玩家是否能获胜(或先手玩家的得分是否大于等于后手玩家)。例如:
- 输入:
[1, 5, 2] - 输出:
False(先手取1或2,后手总能取到5,先手输)。
解题过程
步骤1:定义状态
- 用
dp[i][j]表示在子数组nums[i..j]中,先手玩家能比后手玩家多得的分数(注意:这里“先手”指的是当前轮次首先行动的一方,不一定是全局的先手)。 - 若
dp[0][n-1] >= 0,则全局先手玩家能获胜。
步骤2:状态转移
- 当
i == j时,只有一个数字,先手直接取走,后手无数字可取。因此dp[i][j] = nums[i]。 - 当
i < j时,先手有两种选择:- 取左端
nums[i]:后手变为子数组nums[i+1..j]的先手,先手在此轮比后手多nums[i] - dp[i+1][j]。 - 取右端
nums[j]:后手变为子数组nums[i..j-1]的先手,先手多nums[j] - dp[i][j-1]。
- 取左端
- 最优策略下,先手会选择最大化自己优势的方案:
dp[i][j] = max(nums[i] - dp[i+1][j], nums[j] - dp[i][j-1])。
步骤3:计算顺序
- 区间长度
len从 1 到n(数组长度)递增计算,确保计算dp[i][j]时,更短的区间dp[i+1][j]和dp[i][j-1]已计算。
步骤4:示例演算
以 nums = [1, 5, 2] 为例:
- 初始化单元素区间:
dp[0][0] = 1,dp[1][1] = 5,dp[2][2] = 2。
- 长度
len = 2:dp[0][1] = max(1 - dp[1][1], 5 - dp[0][0]) = max(1-5, 5-1) = max(-4, 4) = 4。dp[1][2] = max(5 - dp[2][2], 2 - dp[1][1]) = max(5-2, 2-5) = max(3, -3) = 3。
- 长度
len = 3:dp[0][2] = max(1 - dp[1][2], 2 - dp[0][1]) = max(1-3, 2-4) = max(-2, -2) = -2。
- 结果:
dp[0][2] = -2 < 0,先手输。
关键点
- 通过差值
dp[i][j]将博弈问题转化为最优化子问题,避免分别记录两名玩家的分数。 - 区间DP通过逐步扩展区间长度,覆盖所有可能的游戏状态。