375. 猜数字大小 II
考点
- 区间DP
思路
一、问题建模
给定一个整数区间 \([1,n]\),其中隐藏着一个未知整数。 算法每次可以选择猜测一个整数 \(x\),并立即支付代价 \(x\)。随后:
- 若真实值小于 \(x\),问题缩小为区间 \([1, x-1]\);
- 若真实值大于 \(x\),问题缩小为区间 \([x+1, n]\);
- 若猜中,则过程结束。
目标是在任意真实值的情况下,都能够保证猜中,并且使得所需支付金额的最大值最小。
该问题本质上是一个 极小化最坏代价(Minimax)问题,并且具有明显的区间最优子结构,适合使用区间动态规划求解。
二、状态定义
定义二维动态规划数组: \[ f[l][r] = \text{当真实答案只可能位于区间 } [l,r] \text{ 内时,保证猜中所需的最小金额} \]
边界条件
- 当 \(l \ge r\) 时,区间中至多只有一个数字,不需要支付任何费用即可确定答案:
\[ f[l][r] = 0 \]
三、决策过程分析
设当前需要处理的区间为 \([l,r]\),选择第一次猜测的数字为 \(x\),其中: \[ l \le x \le r \]
代价拆分
- 本次猜测立即支付代价:\(x\)
- 若真实值小于 \(x\),进入左子区间 \([l, x-1]\),额外代价为 \(f[l][x-1]\)
- 若真实值大于 \(x\),进入右子区间 \([x+1, r]\),额外代价为 \(f[x+1][r]\)
由于需要保证在最坏情况下仍然有足够的金额,因此需要取左右子区间代价的最大值: \[ \text{WorstCost}(x) = x + \max\bigl(f[l][x-1], f[x+1][r]\bigr) \]
四、状态转移方程
为了使最坏情况下的总代价最小,应在所有可能的猜测 \(x\) 中取最优值: \[ \boxed{ f[l][r] = \min_{x \in [l,r]} \left( x + \max\bigl(f[l][x-1], f[x+1][r]\bigr) \right) } \] 这是该问题的核心状态转移方程。
五、计算顺序
由于状态 \(f[l][r]\) 依赖于更短的区间:
- \(f[l][x-1]\)
- \(f[x+1][r]\)
因此按区间长度从小到大进行动态规划:
- 枚举区间长度 \(\text{len} = 2 \sim n\)
- 根据区间长度确定左右端点
- 枚举区间内的所有猜测点 \(x\)
最终答案为: \[ f[1][n] \]
六、空区间的处理
当 \(x = l\) 或 \(x = r\) 时,会出现空区间:
- \([l, x-1]\) 或 \([x+1, r]\)
这些区间在语义上表示「无需再猜」,其代价应当为 0。 实现中必须显式处理这一情况,避免错误使用初始化的无穷大值。
七、AC代码
1 | class Solution { |
八、总结
- 本题通过区间 DP 对「最坏情况下的最优决策」进行建模;
- 状态设计的关键在于:
- 使用区间 \([l,r]\) 表示信息状态;
- 将猜测数字本身作为代价;
- 通过
min + max实现 Minimax 思想;
- 正确处理空区间是实现正确性的关键细节。