当前位置:首页 > 牛客 > 牛客12533题解析:动态规划求解最大乘积问题(附代码实现)

牛客12533题解析:动态规划求解最大乘积问题(附代码实现)

2个月前 (07-18)

牛客12533题解析:动态规划求解最大乘积问题(附代码实现) 牛客题解 动态规划 C++ 二维数组 第1张

一、题目解读

牛客12533题要求从n个人中选择k个人,使他们的能力值乘积最大,且相邻两人编号差不超过d。需考虑正负数的乘积组合情况,通过优化算法找到最优解。

二、解题思路

采用动态规划(Dynamic Programming)解决。定义二维数组dp_max[i][j]和dp_min[i][j],分别表示选j个人且最后一个人为i时的最大和最小乘积。通过状态转移方程,利用前j-1个人的乘积与当前能力值计算,兼顾正×正、负×负、正×负三种情况,避免重复计算。

三、解题步骤

1. 初始化:选1人时,乘积即其能力值。

2. 循环处理选j个人(2≤j≤k),当前人i从j到n遍历。

3. 前一个人l在[i-d, i-1]范围内,计算最大/最小乘积:

○ dp_max[i][j] = max(dp_max[l][j-1] * ability[i-1], dp_min[l][j-1] * ability[i-1])

○ dp_min[i][j] = min(dp_max[l][j-1] * ability[i-1], dp_min[l][j-1] * ability[i-1])

4. 最终结果:遍历dp_max[k][i](i=k到n)取最大值。

四、代码与注释

#include <iostream>
#include <vector>
#include <climits>
using namespace std;

long long maxProduct(int n, vector<int>& ability, int k, int d) {
    // dp_max[i][j]表示选j个人,最后一个人是i时的最大乘积
    // dp_min[i][j]表示选j个人,最后一个人是i时的最小乘积
    vector<vector<long long>> dp_max(n+1, vector<long long>(k+1, LLONG_MIN));
    vector<vector<long long>> dp_min(n+1, vector<long long>(k+1, LLONG_MAX));
    
    // 初始化:选1个人时就是自己的能力值
    for(int i = 1; i <= n; i++) {
        dp_max[i][1] = ability[i-1];
        dp_min[i][1] = ability[i-1];
    }
    
    for(int j = 2; j <= k; j++) { // 选j个人
        for(int i = j; i <= n; i++) { // 当前选第i个人
            // 前一个人只能在[i-d, i-1]范围内
            int start = max(j-1, i-d); // 至少需要j-1个人
            for(int l = start; l < i; l++) {
                // 考虑三种情况:正×正,负×负,正×负
                dp_max[i][j] = max(dp_max[i][j], 
                                  max(dp_max[l][j-1] * ability[i-1], 
                                     dp_min[l][j-1] * ability[i-1]));
                dp_min[i][j] = min(dp_min[i][j], 
                                  min(dp_max[l][j-1] * ability[i-1], 
                                     dp_min[l][j-1] * ability[i-1]));
            }
        }
    }
    
    // 找出选k个人时的最大乘积
    long long result = LLONG_MIN;
    for(int i = k; i <= n; i++) {
        result = max(result, dp_max[i][k]);
    }
    return result;
}

int main() {
    int n, k, d;
    cin >> n;
    vector<int> ability(n);
    for(int i = 0; i < n; i++) cin >> ability[i];
    cin >> k >> d;
    
    cout << maxProduct(n, ability, k, d) << endl;
    return 0;
}

五、总结

本解法通过动态规划将复杂问题分解为子问题,利用状态转移优化时间复杂度。关键在于处理正负数的乘积逻辑,确保最终结果正确。代码结构清晰,注释明确,适用于同类最大乘积问题的参考与学习。


原创内容 转载请注明出处

分享给朋友:

相关文章

力扣119题:从O(n²)到O(2n):杨辉三角高效空间优化

力扣119题:从O(n²)到O(2n):杨辉三角高效空间优化

题目重解:给定一个非负索引 rowIndex,返回杨辉三角的第 rowIndex 行。不同于生成整个杨辉三角,这道题要求我们只返回特定行,且空间复杂度应尽可能优化。例如输入3,需要返回[1,3,3,1...

力扣1137题:动态规划解泰波那契数 高效求解第N项的秘密

力扣1137题:动态规划解泰波那契数 高效求解第N项的秘密

一:重新解读题目泰波那契数列是一个充满数学趣味的递推序列:从第3项开始,每个数均为前三个数的和(即Tₙ₊₃ = Tₙ + Tₙ₊₁ + Tₙ₊₂)。当给定整数n时,需要高效计算出第n项的值。面对此类递...

NOIP2005 普及组 洛谷P1408 背包问题的空间优化技巧与实战应用

NOIP2005 普及组 洛谷P1408 背包问题的空间优化技巧与实战应用

题目重解想象你是一名药师,有t分钟在山上采集m种草药。每种草药需要time分钟采集,价值为num。这就像考试时分配时间做题,要选择收益最大的题目组合。题目要求计算在规定时间内能获得的最大草药价值。解题...

IOI 1994 洛谷1216:如何用O(1)空间解决数字三角形问题?附代码实现

IOI 1994 洛谷1216:如何用O(1)空间解决数字三角形问题?附代码实现

题目重解:数字三角形是一个经典的动态规划问题,给定一个由数字组成的三角形结构,从顶部出发,每次可以移动到下方相邻的数字,最终到达底部。我们需要找到一条路径,使得路径上经过的数字总和最大。这个问题可以很...

2024年GESP五级武器强化(洛谷B4071)解题代码C++版

2024年GESP五级武器强化(洛谷B4071)解题代码C++版

一、题目解读    2024年GESP(青少年软件编程能力等级考试)五级中的“武器强化”(洛谷平台题目编号B4071)是一道典型的算法优化问题。题目要求通过合理...

NOIP 2008火柴棒等式题解(C++代码实现)  动态规划与枚举算法详解

NOIP 2008火柴棒等式题解(C++代码实现) 动态规划与枚举算法详解

一、题目解读火柴棒等式问题(NOIP 2008,洛谷P1149)要求使用给定数量的火柴棒,构造形如 A + B = C 的等式,其中A、B、C均为整数,且火柴棒总数恰好等于输入值。需统计符合条件的等式...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。