
经过深入分析和讨论,我们确定了以下的动态规划转移方程。对于给定的数字序列,我们根据每个数字的正负情况进行分类讨论。
如果当前数字 `nums[i]` 大于0,那么最大值的DP状态 `maxn[i]` 取决于当前数字与前一状态最大值 `maxn[i – 1]` 的乘积和当前数字本身的大小,取其中较大的值。同样,最小值的DP状态 `minn[i]` 取决于当前数字与前一状态最小值 `minn[i – 1]` 的乘积和当前数字本身的大小,取其中较小的值。
反之,如果当前数字 `nums[i]` 小于或等于0,那么最大值的DP状态 `maxn[i]` 将考虑当前数字与前一状态最小值 `minn[i – 1]` 的乘积和当前数字本身的大小,取其中较大的值。最小值的DP状态 `minn[i]` 则考虑当前数字与前一状态最大值 `maxn[i – 1]` 的乘积和当前数字本身的大小,取其中较小的值。
这个问题基于最优子结构原则,通过否定初始的假设,进一步观察题目的特性,最终确定了新的DP状态。并通过分类讨论的方式,逐步推导出了DP转移方程,从而成功地解决了这个问题。
以下是使用C++实现的代码:
cpp
class Solution {
public:
vector maxn, minn;
int maxProduct(vector& nums) {
int n = nums.size(), ans = nums[0];
maxn.resize(n);
minn.resize(n);
maxn[0] = minn[0] = nums[0];
for (int i = 1; i
// 根据nums[i]的正负情况进行分类讨论
if(nums[i] > 0) {
maxn[i] = max(nums[i], maxn[i – 1] nums[i]); // 更新最大值状态
minn[i] = min(nums[i], minn[i – 1] nums[i]); // 更新最小值状态
} else {
maxn[i] = max(nums[i], minn[i – 1] nums[i]); // 更新最大值状态,考虑负数情况
minn[i] = min(nums[i], maxn[i – 1] nums[i]); // 更新最小值状态,考虑负数情况
}
// 更新全局答案
ans = max(ans, maxn[i]);
}
return ans;
}
};
关于DP问题的解题思路
一、确定DP状态:这是解决DP问题的第一步,需要明确问题的最优解与哪些子问题的最优解有关。
二、确定最优子结构原则:DP状态的最优值应该能够由更小规模的DP状态的最优值推导出来。
三、确定无后效性原则:DP状态的获取方式不应影响后续其他DP状态的取值,即已经计算出的子问题的解在未来不会被改变。
四、确定DP转移方程:通过分类讨论和细致枚举,推导出DP状态之间的转移方程,从而解决问题。
