找回密码
 立即注册
查看: 11|回复: 0

牛客网12533,合唱团题解:乘积**化问题的动态规划解法

[复制链接]
  • 打卡等级:即来则安
  • 打卡总天数:18
  • 打卡月天数:2
  • 打卡总奖励:194
  • 最近打卡:2025-08-14 15:12:44

22

主题

8

回帖

1万

积分

VIP

积分
10219
发表于 2025-8-14 15:23:48 | 显示全部楼层 |阅读模式
截图未命名.jpg
一、问题分析与算法设计
这是一个典型的动态规划问题,需要考虑正负值对乘积的影响。我们需要维护两个DP数组:一个记录**值,一个记录最小值(因为负负得正)。
二、C++代码实现
  1. #include <iostream>
  2. #include <vector>
  3. #include <climits>
  4. using namespace std;

  5. long long maxProduct(int n, vector<int>& ability, int k, int d) {
  6.     // dp_max[i][j]表示选j个人,**一个人是i时的**乘积
  7.     // dp_min[i][j]表示选j个人,**一个人是i时的最小乘积
  8.     vector<vector<long long>> dp_max(n+1, vector<long long>(k+1, LLONG_MIN));
  9.     vector<vector<long long>> dp_min(n+1, vector<long long>(k+1, LLONG_MAX));
  10.    
  11.     // 初始化:选1个人时就是自己的能力值
  12.     for(int i = 1; i <= n; i++) {
  13.         dp_max[i][1] = ability[i-1];
  14.         dp_min[i][1] = ability[i-1];
  15.     }
  16.    
  17.     for(int j = 2; j <= k; j++) { // 选j个人
  18.         for(int i = j; i <= n; i++) { // 当前选第i个人
  19.             // 前一个人只能在[i-d, i-1]范围内
  20.             int start = max(j-1, i-d); // 至少需要j-1个人
  21.             for(int l = start; l < i; l++) {
  22.                 // 考虑三种情况:正×正,负×负,正×负
  23.                 dp_max[i][j] = max(dp_max[i][j],
  24.                                   max(dp_max[l][j-1] * ability[i-1],
  25.                                      dp_min[l][j-1] * ability[i-1]));
  26.                 dp_min[i][j] = min(dp_min[i][j],
  27.                                   min(dp_max[l][j-1] * ability[i-1],
  28.                                      dp_min[l][j-1] * ability[i-1]));
  29.             }
  30.         }
  31.     }
  32.    
  33.     // 找出选k个人时的**乘积
  34.     long long result = LLONG_MIN;
  35.     for(int i = k; i <= n; i++) {
  36.         result = max(result, dp_max[i][k]);
  37.     }
  38.     return result;
  39. }

  40. int main() {
  41.     int n, k, d;
  42.     cin >> n;
  43.     vector<int> ability(n);
  44.     for(int i = 0; i < n; i++) cin >> ability[i];
  45.     cin >> k >> d;
  46.    
  47.     cout << maxProduct(n, ability, k, d) << endl;
  48.     return 0;
  49. }
复制代码


三、算法解析
  • 数据结构设计

    • 使用两个二维数组分别存储**值和最小值
    • 考虑正负值对乘积的影响

  • 关键处理逻辑

    • 三重循环处理状态转移
    • 每次考虑前d个位置的可能情况
    • 同时维护**值和最小值

  • 复杂度分析

    • 时间复杂度:O(nkd)
    • 空间复杂度:O(n*k)

来源:牛客网12533,合唱团题解:乘积**化问题的动态规划解法

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

SEO网站 ( 冀ICP备2025113422号-2 )|网站地图

Powered by Discuz! X3.5

快速回复 返回顶部 返回列表