【C++】牛客——WY6 合唱团

✨题目链接:

WY6 合唱团icon-default.png?t=N7T8https://www.nowcoder.com/practice/661c49118ca241909add3a11c96408c8?tpId=122&tqId=33652&ru=/exam/oj


✨题目描述 

有 n 个学生站成一排,每个学生有一个能力值,牛牛想从这 n 个学生中按照顺序选取 k 名学生,要求相邻两个学生的位置编号的差不超过 d,使得这 k 个学生的能力值的乘积最大,你能返回最大的乘积吗?

✨输入描述:

每个输入包含 1 个测试用例。每个测试数据的第一行包含一个整数 n (1 <= n <= 50),表示学生的个数,接下来的一行,包含 n 个整数,按顺序表示每个学生的能力值 ai(-50 <= ai <= 50)。接下来的一行包含两个整数,k 和 d (1 <= k <= 10, 1 <= d <= 50)。

✨输出描述:

输出一行表示最大的乘积。


 

✨示例1


📍输入

3
7 4 7
2 50



📍输出

49


📍说明

输出一行表示最大的乘积。


✨解题思路

  • 考虑以第i(i < n)个元素结尾作为选择的第k(k < K)个值
  • 以前d个元素中最大的k-1个元素的乘积来更新当前元素的最大乘积
  • 由于(-50 <= ai <= 50),存在负数,因此当第i个值为负数时,考虑前d个元素的最小值作为更新依据 因此状态转移方程为:
  • dpMAX[i][k]=max(dpMAX[i][k],max(dpMAX[j][k−1]∗arr[i],dpMIN[j][k−1]∗arr[i]))

    dpMIN[i][k]=min(dpMIN[i][k],min(dpMAX[j][k−1]∗arr[i],dpMIN[j][k−1]∗arr[i]))

    最终答案为max(dpMAX[i][K],0<=i<n)


✨代码
 

#include <iostream>
#include <limits.h>
#include <vector>
using namespace std;

typedef long long ll;

const int INF = LLONG_MAX;
const int MINF = LLONG_MIN;

void solve(int n, int K, int d, vector<int>& arr){
    vector<vector<ll>> dpMAX(n,vector<ll>(K+1,0)); // 最大值
    vector<vector<ll>> dpMIN(n,vector<ll>(K+1,0)); // 最小值,由于存在负数,否则直接计算最大值即可
    
    for(int i = 0; i < n; ++i){ // 初始化k=1时,以当前元素结尾的最大最小值
        dpMAX[i][1] = arr[i];
        dpMIN[i][1] = arr[i];
    }
    
    ll ans = MINF;
    
    for(int i = 0; i < n; ++i){
        for(int k = 2; k <= min(i+1,K); ++k){ 
            for(int j = max(0, i-d); j < i; ++j){ // 再坐标差值<=d的范围内更新
                dpMAX[i][k] = max( // 更新最大值
                    dpMAX[i][k], max(dpMAX[j][k-1]*arr[i], dpMIN[j][k-1]*arr[i])
                );
                
                dpMIN[i][k] = min( // 更新最小值
                    dpMIN[i][k], min(dpMAX[j][k-1]*arr[i], dpMIN[j][k-1]*arr[i])
                );
                
            }
        }
        ans = max(ans, dpMAX[i][K]); // 更新结果
    }
    cout<<ans<<endl;
    return;
}

int main(){

    int n,k,d;
    cin>>n;
    vector<int> arr(n);
    for(int i = 0; i < n; ++i){
        cin>>arr[i];
    }
    cin>>k>>d;
    solve(n,k,d,arr);
    return 0;
}


※ 如果文章对你有帮助的话,可以点赞收藏!!谢谢支持

  • 30
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一岁就可帅-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值