1.状态定义
可以定义状态为一个二维数组 dp[i][j][k] ,其中 i 表示考虑到前 i 个甜点, j 表示已经使用了 j 个魔法棒, k 表示当前甜点喜爱值之和为 k 。其值代表满足对应情况的方案数,初始时大部分值设为0,边界情况根据题意设定。
2.状态转移
对于每个甜点,有两种选择,用魔法棒或者不用魔法棒。若不用魔法棒, dp[i][j][k] 可以由 dp[i - 1][j][k - 当前甜点喜爱值] 转移而来;若用魔法棒, dp[i][j][k] 可从 dp[i - 1][j - 1][k - 当前甜点喜爱值的阶乘] 转移过来,通过这两种情况不断更新状态数组。
3.最终答案
最终答案就是 dp[N][M][S] 的值,即考虑完所有 N 个甜点,用了 M 个魔法棒后,喜爱值之和恰好为 S 的不同方案的数量。
4.复杂度分析
- 时间复杂度:有三层循环,分别遍历 N 个甜点、 M 个魔法棒以及最大可能的喜爱值之和(设为 V ),所以时间复杂度大致为 O(N * M * V) ,其中 V 取决于输入的喜爱值范围等情况。
- 空间复杂度:定义的状态数组 dp 的维度是 N * M * V ,所以空间复杂度为 O(N * M * V) ,不过可以通过滚动数组等优化手段适当减少空间占用情况。
这道题通过合理定义状态与状态转移关系来统计满足条件的方案数,需要仔细分析各种情况并考虑复杂度对算法的影响。
5.代码实现
6.心得体会
分析这道甜点相关的方案问题后,收获颇多。在状态定义上,构建二维数组来涵盖甜点数量、魔法棒使用数及喜爱值总和等关键要素,清晰呈现问题状态,让我体会到合理定义的重要性。 状态转移过程,依据用或不用魔法棒的不同情况去更新状态,逻辑严谨且环环相扣,很考验思维细致程度。 最终答案藏在状态数组特定位置中,让我明白有序推导的意义。复杂度分析则提醒着要兼顾时间与空间,优化算法避免资源浪费。 这题不仅锻炼了逻辑推理与动态规划思维,更让我意识到面对复杂问题,需抽丝剥茧找思路,巧妙定义状态、规划转移,才能高效解决问题,往后遇到类似题也更有底气了。