1 条题解
-
0
题解:最小花费购买皮肤方案
问题转化
有 个英雄,英雄 有 款皮肤,每款价格 。如果给英雄 购买了 款皮肤(),则展示策略数为:
需要满足:
总花费为:
求最小总花费。
约束条件
- (极大)
- ,
- ,最大 (因为 ,但实际通常更小)
动态规划思路
1. 状态设计
由于 很大但 很小,且 ,考虑 DP 状态为已经考虑了前 个英雄,当前乘积为 的最小花费。
但 可能达到 太大,需要压缩。
2. 乘积压缩
注意到 ,如果乘积已经 ,可以直接视为 ,因为更大的乘积不会让花费更小(价格非负)。
因此定义 表示考虑前 个英雄,当前乘积为 (但 )的最小花费。当 时统一记作 。
由于 很小,状态数可控。
3. 转移方程
初始化 ,其他 。
对于英雄 :
$$dp[i][\min(M, p \times b)] = \min(dp[i][\min(M, p \times b)],\ dp[i-1][p] + b \times C_i) $$其中 ,但注意 时乘积为 0,不合法(因为最终乘积至少为 才能大于等于 当 )。实际上我们不允许 ,因为题目要求“只玩有皮肤的英雄”,所以 。
但样例中英雄皮肤数可以为 ,意思是如果 则不能选该英雄展示?不,题目说“对于有皮肤的每一个英雄”,所以如果 则该英雄不能选(即 ),但此时展示策略数会乘以 ,因此必须所有英雄 才有效。
所以约束:。
4. 状态数量优化
最大 ,但 ,每个 ,总乘积可能非常大,但超过 后统一记为 。
因此 的可能取值是由若干个不超过 的数相乘得到,且不超过 。这样的数不会太多(本质是 以内形如 的数)。
实际上,,因子只有 (因为 ,可能的质因子只有 )。
估算状态数:设 ,且 。
,
,
,
。理论最大状态数约 $58\times 37\times 25\times 20 \approx 1.07\times 10^6$,但实际小得多,因为乘积增长快。
5. 使用哈希表存储状态
用 unordered_map 存储 dp 状态:key = 乘积 ,value = 最小花费。
每次转移时枚举 ,更新新乘积对应的最小花费。6. 算法步骤
- 读入
- 初始化 dp 字典:dp[1] = 0(乘积为 1 花费 0)
- 对每个英雄 :
- 创建新字典 ndp
- 遍历 dp 中每个状态 (prod, cost)
- 枚举 到 :
- 新乘积 new_prod = prod * b
- 如果 new_prod >= M,令 new_prod = M
- 新花费 new_cost = cost + b * C_i
- 更新 ndp[new_prod] = min(ndp[new_prod], new_cost)
- dp = ndp
- 答案 = dp[M](因为最后乘积至少为 M)
7. 复杂度分析
- 状态数约 量级
- 每个状态枚举 ,转移
- 总复杂度 ,可过
8. 特例处理
- 若 ,则答案为 (每个英雄买 1 款皮肤)
- 若有 的英雄,则无解(但题目保证有解)
最终答案
输出 dp[M] 即可。
- 1
信息
- ID
- 6066
- 时间
- 1400ms
- 内存
- 512MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者