最大连续子序列积

最大连续子序列积

题目描述:

给定一个浮点数序列(可能有正数、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
AC代码:
#include<cstdio>
#include<cstdlib>
#define MAX 100001

using namespace std;

double Array[MAX];
double Max[MAX];
double Min[MAX];

double Maxnum(double a,double b,double c)
{
	double max;
	if((a>=b&&b>=c)||(a>=c&&c>=b))
		max=a;
	if((b>=a&&a>=c)||(b>=c&&c>=a))
		max=b;
	if((c>=a&&a>=b)||(c>=b&&b>=a))
		max=c;
	return max;
}

double Minnum(double a,double b,double c)
{
	double min;
	if((a<=b&&b<=c)||(a<=c&&c<=b))
		min=a;
	if((b<=a&&a<=c)||(b<=c&&c<=a))
		min=b;
	if((c<=a&&a<=b)||(c<=b&&b<=a))
		min=c;
	return min;
}

int main(int argc,char *argv[])
{
	int i,n;
	double maxans;
	while(scanf("%d",&n)!=EOF)
	{
		for(i=0;i<n;i++)
			scanf("%lf",&Array[i]);
		maxans=Max[0]=Min[0]=Array[0];
		for(i=1;i<n;i++)//动态规划求解
		{
			Max[i]=Maxnum(Array[i],Max[i-1]*Array[i],Min[i-1]*Array[i]);
			Min[i]=Minnum(Array[i],Max[i-1]*Array[i],Min[i-1]*Array[i]);
			if(Max[i]>maxans)
				maxans=Max[i];
		}
		if(maxans>=0)
		{//判断是否为浮点数
			if(maxans-(int)maxans==0)
				printf("%d\n",(int)maxans);
			else
				printf("%.2f\n",maxans);
		}
		else
			printf("-1\n");
	}

	return 0;
}


分析:假设数组为a[],直接利用动归来求解,考虑到可能存在负数的情况,我们用Max[i]来表示以a[i]结尾的最大连续子序列的乘积值,用Min[i]表示以a[i]结尾的最小的连续子序列的乘积值,那么状态转移方程为:
       Max[i]=max{a[i], Max[i-1]*a[i], Min[i-1]*a[i]};
       Min[i]=min{a[i], Max[i-1]*a[i], Min[i-1]*a[i]};
因为数组里有负数,所以保存最小值很有必要,负数乘以负数是一个正数。。。
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值