【算法题】合唱团

xiaoxiao2021-02-28  109

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

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

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

输入例子: 3 7 4 7 2 50

输出例子: 49


动态规划:

考虑前i名学生:

F(i,j) 表示前i名学生中选择j个,且最后一个:第i个学生被选中时,正乘积的最大值

H(i,j) 表示前i名学生中选择j个,且最后一个:第i个学生被选中时,负乘积的最小值

例如:4 7 -5 7 则

F(1,1) = 4 ; H(1,1)=0 F(2,1) = 7 ; H(2,1)=0 F(3,1) = 0 ; H(3,1) = -5 F(4,1) = 7 ; H(3,1) = 0

F(2,2) = 28 ; H(2,2) = 0 F(3,2) = 0 ; H(3,2) = -35 F(4,2) = 49; H(4,2) = -35

F(3,3) = 0 ; H(3,3) = -140 F(4,3) = 196 ; H(4,3) = -245


状态转移方程:

if(a[i]>0):

F(i,j)=maxa[i]F(i1)(j1)a[i]F(i2)(j1)...a[i]F(id)(j1) H(i,j)=maxa[i]H(i1)(j1)a[i]H(i2)(j1)...a[i]H(id)(j1) if(a[i]<0): F(i,j)=maxa[i]H(i1)(j1)a[i]H(i2)(j1)...a[i]H(id)(j1) H(i,j)=maxa[i]F(i1)(j1)a[i]F(i2)(j1)...a[i]F(id)(j1)


max(n,k)=max{F(i,k)|0=<i<=n}


#include <iostream> #include <numeric> #include<algorithm> #include <string> #include<hash_map> using namespace std; //#define debug_ long long func(vector<int> vec, int k, int d) { int n = vec.size(); vector<vector<long long>> MaxPos; vector<vector<long long>> MinNeg; MaxPos.resize(n + 1); MinNeg.resize(n + 1); for (auto i = 0; i < MaxPos.size();++i) { MaxPos[i].resize(k + 1); MinNeg[i].resize(k + 1); } for (auto i = 1; i <= n;++i) { if (vec[i-1]>0) { MaxPos[i][1] = vec[i-1]; } if (vec[i-1]<0) { MinNeg[i][1] = vec[i-1]; } } long long tmp_maxpos,tmp_minneg; for (auto i = 2; i <= n; ++i) { for (auto j = 2; j <= k; ++j) { if (i<j) { continue; } tmp_maxpos = 0; tmp_minneg = 0; for (auto t = i - 1;( t >= i - d && t > 0);--t) { if (tmp_maxpos<MaxPos[t][j - 1]) { tmp_maxpos = MaxPos[t][j - 1]; } if (tmp_minneg > MinNeg[t][j - 1]) { tmp_minneg = MinNeg[t][j - 1]; } } if (vec[i-1]>0) { MaxPos[i][j] = tmp_maxpos*vec[i-1]; MinNeg[i][j] = tmp_minneg*vec[i-1]; } if (vec[i-1]<0) { MaxPos[i][j] = tmp_minneg*vec[i-1]; MinNeg[i][j] = tmp_maxpos*vec[i-1]; } } } long long result(0); for (auto i = 0; i < MaxPos.size();++i) { if (result<MaxPos[i][k]) { result = MaxPos[i][k]; } } return result; } int main() { int n, k, d; vector<int> vec; #ifdef debug_ n = 7; vec.push_back(0); vec.push_back(7); vec.push_back(4); vec.push_back(7); vec.push_back(-5); vec.push_back(7); vec.push_back(-47); k = 3; d = 2; #else cin >> n; vec.resize(n); for (auto i = 0; i < n;++i) { cin >> vec[i]; } cin >> k >> d; #endif cout << func(vec, k, d) << endl; return 0; }
转载请注明原文地址: https://www.6miu.com/read-84218.html

最新回复(0)