1 条题解
-
0
问题分析
本题是一道基于区间动态规划(DP) 的博弈问题,核心任务是模拟两人轮流从序列两端取数的过程,计算双方的最优得分。每个数字有其首次出现位置(
d数组)和末次出现位置(c数组),取数时若满足特定条件可获得分数,最终需输出双方的最大得分比。算法思路
1. 预处理数组
d[x]:记录数字x在序列中首次出现的位置。c[x]:记录数字x在序列中末次出现的位置。- 这两个数组用于判断取数时是否满足得分条件。
2. 得分判定函数(
cost)判断在区间
[l, r]中取位置x的数字是否能得分:- 若
x是数字a[x]的首次出现位置(x == d[a[x]]),且区间右端点r不小于该数字的末次出现位置(r >= c[a[x]]),则得1分。 - 若
x是数字a[x]的末次出现位置(x == c[a[x]]),且区间左端点l不大于该数字的首次出现位置(l <= d[a[x]]),则得1分。 - 否则得0分。
3. 区间DP状态定义
dp[l][r][turn]:表示在区间[l, r]中,当前轮到turn(0或1,代表两位玩家)取数时,当前玩家能获得的最大得分,以及另一玩家的对应得分。dp[l][r][0]:玩家0的最大得分。dp[l][r][1]:玩家1的最大得分。
4. DP状态转移
- 边界条件:当区间长度为1(
l == r)时,当前玩家只能取该位置的数,得分由cost函数判定,另一玩家得0分。 - 递归转移:对于区间
[l, r],当前玩家有两种选择:- 取左端点
l:得分 = 左半区间[l+1, r]中另一玩家的状态得分 + 当前取l的得分(cost(l, r, l))。 - 取右端点
r:得分 = 右半区间[l, r-1]中另一玩家的状态得分 + 当前取r的得分(cost(l, r, r))。
- 取左端点
- 选择策略:
- 若两种选择得分不同,取得分更高的选项,另一玩家得分对应更新。
- 若得分相同,取另一玩家得分更小的选项(保证当前玩家最优的同时,最小化对手得分)。
5. 结果输出
最终答案为
dp[1][n][0] : dp[1][n][1],即玩家0和玩家1在整个区间[1, n]上的最优得分比。关键复杂度分析
- 时间复杂度:区间DP的状态总数为
O(n^2 * 2)(n为序列长度,2代表两位玩家),每个状态的计算涉及两次递归调用和常数次操作,故总复杂度为O(n^2)。 - 空间复杂度:DP数组存储所有区间和玩家状态,空间复杂度为
O(n^2),适合n <= 3000的规模。
代码解析
模块 功能描述 预处理 读取序列,计算每个数字的首次出现位置 d和末次出现位置c。得分函数 cost判断取数时是否满足得分条件,返回0或1。DP递归函数 get(l, r, turn)递归计算区间[l, r]中当前玩家的最优得分,更新dp数组。主函数 初始化DP数组,调用递归函数计算结果,输出得分比。 算法的核心是通过区间DP模拟博弈过程,利用递归和记忆化存储避免重复计算,确保双方在每一步都做出最优选择,最终得到全局最优的得分比。
- 1
信息
- ID
- 3640
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者