时间限制:1秒
空间限制:32768K
热度指数:43082
算法知识视频讲解
题目描述
有 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
#include <bits/stdc++.h> using namespace std; int a[111]; long long dp[55][55][2]; int main(){ int n, K, d; cin >> n; long long ans = -1e9; for(int i = 1; i <= n; ++i){ cin >> a[i]; } cin >> K >> d; for(int i = 1; i <= n; ++i){ if(a[i] >= 0){ dp[i][1][0] = a[i]; dp[i][1][1] = 1; } else{ dp[i][1][1] = a[i]; dp[i][1][0] = -1; } for(int j = 2; j <= K; ++j){ for(int k = i - 1; k >= max(1, i - d); --k){ if(a[i] >= 0){ if(dp[k][j - 1][0] >= 0){ dp[i][j][0] = max(dp[i][j][0], dp[k][j - 1][0] * a[i]); } if(dp[k][j - 1][1] < 0){ dp[i][j][1] = min(dp[i][j][1], dp[k][j - 1][1] * a[i]); } } if(a[i] < 0){ if(dp[k][j - 1][0] >= 0){ dp[i][j][1] = min(dp[i][j][1], dp[k][j - 1][0] * a[i]); } if(dp[k][j - 1][1] < 0){ dp[i][j][0] = max(dp[i][j][0], dp[k][j - 1][1] * a[i]); } } } } } for(int i = 1; i <= n; ++i){ if(dp[i][K][0] >= 0){ ans = max(ans, dp[i][K][0]); } if(dp[i][K][1] <= 0){ ans = max(ans, dp[i][K][1]); } } cout << ans << endl; } /* 题意: 选择k个数,数字之间距离不超过d,使得k个数乘积最大。 思路: 线性dp,对于每个位置维护一下最大正值最小负值。 */