最大连续子序列乘积(小米手机2013年校园招聘笔试题)

题目描述:
给定一个浮点数序列(可能有正数、0和负数),求出一个最大的连续子序列乘积。

 

输入:

输入可能包含多个测试样例。
每个测试样例的第一行仅包含正整数 n(n<=100000),表示浮点数序列的个数。
第二行输入n个浮点数用空格分隔。
输入数据保证所有数字乘积在双精度浮点数表示的范围内。

 

输出:

对应每个测试案例,输出序列中最大的连续子序列乘积,若乘积为浮点数请保留2位小数,如果最大乘积为负数,输出-1。

 

样例输入:
7
-2.5 4 0 3 0.5 8 -1
5
-3.2 5 -1.6 1 2.5
5
-1.1 2.2 -1.1 3.3 -1.1
样例输出:
12
64
8.78


状态dpMax[i]表示以arr[i]结尾的最大连续子串乘积值,dpMin[i]表示以arr[i]结尾的最小连续子串乘积值(考虑到负数的情况)。

状态转移方程:    dpMax[i]=maxVal(arr[i],arr[i]*dpMin[i-1],arr[i]*dpMax[i-1]);

                        dpMin[i]=minVal(arr[i],arr[i]*dpMin[i-1],arr[i]*dpMax[i-1]);

Code:
#include <cstdio>
 
using namespace std;
 
void initDp(double dp[],int length){
    for(int i=0;i<length;++i)
        dp[i]=0;
}
 
double maxVal(double a,double b,double c){
    return a>b?(a>c?a:c):(b>c?b:c);
}
 
double minVal(double a,double b,double c){
    return a<b?(a<c?a:c):(b<c?b:c);
}
 
const int arrSize=100010;
double arr[arrSize],dpMin[arrSize],dpMax[arrSize];
 
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF){
        for(int i=0;i<n;++i)
            scanf("%lf",&arr[i]);
        initDp(dpMin,n);
        initDp(dpMax,n);
        if(n==1&&arr[0]<0){
            printf("%d
",-1);
            continue;
        }
        dpMin[0]=dpMax[0]=arr[0];
        for(int i=1;i<n;++i){
            dpMax[i]=maxVal(arr[i],arr[i]*dpMin[i-1],arr[i]*dpMax[i-1]);
            dpMin[i]=minVal(arr[i],arr[i]*dpMin[i-1],arr[i]*dpMax[i-1]);
        }
        double answer=0;
        for(int i=0;i<n;++i){
            if(dpMax[i]>answer)
                answer=dpMax[i];
        }
        double tmp=answer-(int)answer;
        if(tmp==0)
            printf("%d
",(int)answer);
        else
            printf("%.2lf
",answer);
    }
    return 0;
}
 
/**************************************************************
    Problem: 1501
    User: lcyvino
    Language: C++
    Result: Accepted
    Time:120 ms
    Memory:3864 kb
****************************************************************/