原题摘录
输入n个元素组成的序列S,你需要找出一个乘积最大的连续子序列.如果这个最大的乘积不是正数,输出0.(1<=n<=18,-10<=Si<=10).
样例输入
3
2 4 -3
5
2 5 -1 2 -1
样例输出
8
20
分析
连续子序列有两个要素:起点和终点,因此只需枚举起点和终点即可.由于每个元素的绝对值不超过10,且不超过18个元素,最大乘积不超过10^18,可以用long long存储.
两种解决方法:暴力求解和动态规划
AC代码(注释)
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <assert.h>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
using namespace std;
int n;
int maxProduct(int nums[]) {
//思路一:暴力求解
//遍历数组元素,每个元素维护一个变量,代表当前的乘积
//全局变量max,最大的乘积
int max = nums[0];
for(int i = 0; i < n; i++) {
int mul = 1;
for(int j = i; j < n; j++) {
mul *= nums[j];
if(mul > max) {//直接在循环内部作比较,而不用算出所有再比较
max = mul;//更新最大值
}
}
}
return max;
}
//int maxProduct(int nums[],int len) {
//思路二:动态规划
//遍历数组,每个元素对应以该元素为结尾的子序列的最大值和最小值两个变量,更新乘积最大值
// int posmax = nums[0], negmin = nums[0], maxn = nums[0];//阳阴
//
// for(int i = 1; i < len; i++) {
// int pre_posmax = posmax;
// int pre_negmin = negmin;
//
// posmax = max(nums[i], max(nums[i]*pre_posmax, nums[i]*pre_negmin));
// negmin = min(nums[i], min(nums[i]*pre_posmax, nums[i]*pre_negmin));
//
// if(max(posmax, negmin) > maxn) {
// maxn = max(posmax, negmin);
// }
// }
// return maxn;
//}
int main(int argc, char** argv)
{
while(cin>>n&&n){
int a[20],i;
long answer;
for(i=0;i<=n-1;i++)
cin>>a[i];
answer=maxProduct(a); //思路一
//answer=maxProduct(a,i); //思路二
if(answer<0) cout<<"0"<<endl;
else cout<<answer<<endl;
}
return 0;
}