有 n 个学生站成一排,每个学生有一个能力值,牛牛想从这 n 个学生中按照顺序选取 k 名学生,要求相邻两个学生的位置编号的差不超过 d,使得这 k 个学生的能力值的乘积最大,你能返回最大的乘积吗?
输入描述:
每个输入包含 1 个测试用例。每个测试数据的第一行包含一个整数 n (1 <= n <= 50),表示学生的个数,接下来的一行,包含 n 个整数,按顺序表示每个学生的能力值 ai(-50 <= ai <= 50)。接下来的一行包含两个整数,k 和 d (1 <= k <= 10, 1 <= d <= 50)。
输出描述:
输出一行表示最大的乘积。#include<iostream> #include<vector> using namespace std; const long long int MIN=(-1LL)<<63; const long long int MAX=(1LL)<<62; long long int maxt(long long int a,long long int b) { return a>b?a:b; } long long int mint(long long int a,long long int b) { return a<b?a:b; } int main() { long long int n; //学生个数 long long int k,d; //k:选取学生个数,d:编号差 while(cin>>n) { long long int* a=new long long int[n]; for(int i=0;i<n;i++) cin>>a[i]; cin>>k>>d; vector< vector<long long int> >dp_max(k+1,vector<long long int>(n+1,MIN)); vector< vector<long long int> >dp_min(k+1,vector<long long int>(n+1,MAX)); //dp_max[i][j]表示当前已选取到第i个学生,此时选取的学生编号为j //因为其中有负数参与运算,因此要计算最大和最小值 long long int result=(-1LL)<<63; int p=0; for(int i=0;i<n;i++) { dp_max[1][i]=a[i]; dp_min[1][i]=a[i]; //以当前为第一个 //cout<<"dp_max["<<1<<"]"<<"["<<i<<"]="<<dp_max[1][i]<<endl; for(int j=2;j<=k&&j<=(i+1);j++) //以当前为第k个 { for(int t=i-1;t>=0&&(i-t)<=d;t--) { if((j-1)>(t+1)) continue; dp_max[j][i]=maxt(dp_max[j][i],maxt(dp_max[j-1][t]*a[i],dp_min[j-1][t]*a[i])); dp_min[j][i]=mint(dp_min[j][i],mint(dp_min[j-1][t]*a[i],dp_max[j-1][t]*a[i])); //if(p<20) //cout<<"dp_max["<<j<<"]"<<"["<<i<<"]="<<dp_max[j][i]<<endl; // p++; } } result=maxt(result,dp_max[k][i]); } cout<<result<<endl; delete[] a; } return 0; } /* 36 7 -15 31 49 -44 35 44 -47 -23 15 -11 10 -21 10 -13 0 -20 -36 22 -13 -39 -39 -31 -13 -27 -43 -6 40 5 -47 35 -8 24 -31 -24 -1 3 31 */
输入例子:
3 7 4 7 2 50
输出例子:
49