动态规划:最大连续子序列乘积

题目描述:

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

分析:若暴力求解,需要O(n^3)时间,太低效,故使用动态规划。

设data[i]:第i个数据,dp[i]:以第i个数结尾的连续子序列最大乘积,

若题目要求的是最大连续子序列和,则易确定状态转移方程为:

dp[i]=max(data[i],dp[i-1]+data[i])(dp[i]为以第i个数结尾的连续子序列最大和)

但乘积存在负负得正的问题,即原本很小的负数成了一个负数反而变大了,(负数逆袭了),

故不能照抄加法的转移方程,为了解决这个问题,需要定义两个数组:

dp1[i]:以第i个数结尾的连续子序列最大乘积

dp2[i]:以第i个数结尾的连续子序列最小乘积

转移方程:

dp1[i]=max(data[i],dp1[i-1]*data[i],dp2[i-1]*data[i]);

dp2[i]=min(data[i],dp1[i-1]*data[i],dp2[i-1]*data[i]);

最后遍历dp1得到最大值即为答案。

代码如下:

#include<stdio.h>
double max(double a,double b){return a>b?a:b;}
double min(double a,double b){return a<b?a:b;}
double dp1[100001];
double dp2[100001];
double data[100001];
double helper(double data[],int n)
{
  dp1[0]=data[0];
  dp2[0]=data[0];
  for(int i=1;i<n;i++)
  {
	  dp1[i]=max(data[i],max(dp1[i-1]*data[i],dp2[i-1]*data[i]));
	  dp2[i]=min(data[i],min(dp1[i-1]*data[i],dp2[i-1]*data[i]));
  }
  double ans=dp1[0];
  for(int i=1;i<n;i++)
  {
	  ans=max(ans,dp1[i]);
  }
  return ans;
}

int main(void)
{
    int i,n;
    while(scanf("%d",&n)!=EOF)
    {
        for(i=0; i<n; ++i)
        {
            scanf("%lf", &data[i]);
        }
        double ans = helper(data, n);
        printf("%lf\n",ans);
    }
    return 0;
}

其实还可以对空间复杂度进行化简,代码如下:

double helper(double data[], int n)
{
    double ans = data[0];
    double localMax = data[0];
    double localMin = data[0];
    for(int i=1; i<n; ++i)
    {
        double t1 = max(data[i], max(localMax*data[i], localMin*data[i]) );
        double t2 = min(data[i], min(localMax*data[i], localMin*data[i]) );

        localMax = t1;
        localMin = t2;

        ans = localMax > ans ? localMax : ans;
    }

    return ans;
}
时间: 2024-10-12 03:47:29

动态规划:最大连续子序列乘积的相关文章

最大连续子序列之和,最大连续子序列乘积

最大连续子序列之和问题描述为:数组中里有正数也有负数,连续的一个或多个整数组成一个子数组,每个子数组都有一个和,求所有子数组的和的最大值.分析,对数组a进行一遍扫描,sum[i] 为前i个元素中,包含第i个元素且和最大的连续子数组,MaxSum保存当前子数组中最大和,对于a[i+1]来说,sum[i+1] = sum[i]+a[i+1],此时如果sum[i+1]<0,那么sum需要重新赋0,从i+1之后开始累加,如果sum[i+1]>0,那么MaxSum = max(MaxSum, Sum[i

最大连续子序列乘积

问题描述 给定一个整数序列(可能有正数,0和负数),求它的一个最大连续子序列乘积.比如给定数组a={3, -4, -5, 6, -2},则最大连续子序列乘积为360,即3*(-4)*(-5)*6=360. 分析 求最大连续子序列乘积与最大连续子序列和问题有所不同,因为其中有正有负还有可能有0. 假设数组为a[],直接利用动归来求解,考虑到可能存在负数的情况,我们用Max[i]来表示以a[i]结尾的最大连续子序列的乘积值,用Min[i]表示以a[i]结尾的最小的连续子序列的乘积值,那么状态转移方程

算法题——最大连续子序列乘积

1 template <typename Comparable> 2 Comparable maxprod( const vector<Comparable>&v) 3 { 4 int i; 5 Comparable maxProduct = 1; 6 Comparable minProduct = 1; 7 Comparable maxCurrent = 1; 8 Comparable minCurrent = 1; 9 //Comparable t; 10 11 for

动态规划——最大连续子序列和

最大连续子序列和问题如下: 下面介绍动态规划的做法,复杂度为 O(n). 步骤 1:令状态 dp[i] 表示以 A[i] 作为末尾的连续序列的最大和(这里是说 A[i] 必须作为连续序列的末尾). 步骤 2:做如下考虑:因为 dp[i] 要求是必须以 A[i] 结尾的连续序列,那么只有两种情况: 这个最大和的连续序列只有一个元素,即以 A[i] 开始,以 A[i] 结尾. 这个最大和的连续序列有多个元素,即从前面某处 A[p] 开始 (p<i),一直到 A[i] 结尾. 对第一种情况,最大和就是

连续子序列的最大乘积

问题描述 给定一个整数序列,序列中可能含有0,正数,负数,求出连续子序列乘积的最大值 暴力解法 双层循环,一一遍历,每次将当前结果与前次结果要比较,如果大于前次结果,更新最大值,时间复杂度为O(n2),复杂度较高,代码略 动态规划解法 对于序列arr,maxDp[k]表示以arr[k](必须包含arr[k])结尾的最大连续子序列乘积值,minDp[k]表示以arr[k](必须包含arr[k])结尾的最小连续子序列乘积值,则对于maxDp[k + 1],表示以arr[k + 1]结尾的最大连续子序

动态规划:最大连续子序列和

问题:给出一个数组,求其连续子序列的最大和 package 动态规划; /** * 给出一个数组,求其连续子数组的最大和 * @author Administrator * */ public class MaxSum { public static void main(String[] args) { int[] arr = new int[]{-3,1,-3,4,-1,2,1}; int max=arr[0]; int current=arr[0]; for(int i=1;i<arr.le

HDU-1231-最大连续子序列(Java+DP动态规划)

最大连续子序列 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 21101    Accepted Submission(s): 9361 Problem Description 给定K个整数的序列{ N1, N2, ..., NK },其任意连续子序列可表示为{ Ni, Ni+1, ..., Nj },其中 1 <= i <= j

动态规划--连续子序列的最大和

给定k个整数的序列{N1,N2,...,Nk },其任意连续子序列可表示为{ Ni, Ni+1, ..., Nj },其中 1 <= i <= j <= k.最大连续子序列是所有连续子序中元素和最大的一个,例如给定序列{ -2, 11, -4, 13, -5, -2 },其最大连续子序列为{11,-4,13},最大连续子序列和即为20. 注:为方便起见,如果所有整数均为负数,则最大子序列和为0. 算法一,穷举法,找出所有子数组,然后求出子数组的和,在所有子数组的和中取最大值 /*O(n^

动态规划经典题目:最大连续子序列和

最大连续子序列和问题 给定k个整数的序列{N1,N2,...,Nk },其任意连续子序列可表示为{ Ni, Ni+1, ..., Nj },其中 1 <= i <= j <= k.最大连续子序列是所有连续子序中元素和最大的一个,例如给定序列{ -2, 11, -4, 13, -5, -2 },其最大连续子序列为{11,-4,13},最大连续子序列和即为20. 注:为方便起见,如果所有整数均为负数,则最大子序列和为0. 解决这样一个问题是一个很有趣的过程,我们可以尝试着从复杂度比较高的算法