最大连续子序列乘积(DP)
- 题目来源:小米手机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
思路:
这道题目和最大连续子字段和是类似的,也是用dp,只是对于每个数(假设该数是第i个数),我们要存放两个状态,一个是前i个数中包含第i个数的连续子段乘积的最大正数,一个是前i个数中包含第i个数的连续子段乘积的最小负数。假设data[i]存放第i个数,ans[i][0]和ans[i][1]分别存放连续子段乘积的最大正数和最小负数。
状态转移具体可以分情况讨论:- 当i = 1时
如果data[i] >= 0,则ans[1][0] = data[1], ans[1][1] = FMAX (FMAX = -0.001, 表示最大负数)
如果data[i] < 0,则ans[1][0] = ZMIN, ans[1][1] = data[1] (ZMIN = 0.001, 表示最小正数) - 当1 < i <= n 时
(1)情况一:如果data[i] >= 0 - 如果ans[i - 1][0] == ZMIN 或者 data[i] * ans[i - 1][0] <= data[i]
ans[i][0] = data[i] - 如果data[i] * ans[i - 1][0] > data[i]
ans[i][0] = data[i] * ans[i - 1][0] - 如果ans[i - 1][1] == FMAX
ans[i][1] = FMAX - 如果ans[i - 1][1] > FMAX
ans[i][1] = ans[i - 1][1] * data[i]
(2)情况二:如果data[i] < 0
- 如果ans[i - 1][0] == ZMIN 或者 data[i] * ans[i - 1][0] <= data[i]
ans[i][1] = data[i] - 如果data[i] * ans[i - 1][0] > data[i]
ans[i][1] = data[i] * ans[i - 1][0] - 如果ans[i - 1][1] == FMAX
ans[i][0] = ZMIN - 如果ans[i - 1][1] > FMAX
ans[i][0] = ans[i - 1][1] * data[i]
这道题需要注意的是浮点数为0的判断,悲剧自己在这上面wa了好几次!!!看来自己对浮点数的理解还是比较模糊!!
1 // 1501.cpp : 定义控制台应用程序的入口点。 2 // 3 4 #include <stdio.h> 5 #include <math.h> 6 7 int n; 8 double data[100000 + 5]; 9 double ans[100000 + 5][2]; 10 double max; 11 12 #define JD 0.0000001 13 14 #define FMAX -0.001 15 #define ZMIN 0.001 16 17 int flag; 18 19 int main(void) 20 { 21 int i; 22 23 // freopen("in.txt", "r", stdin); 24 while (scanf("%d", &n) != EOF) 25 { 26 flag = 0; 27 for (i = 1; i <= n; i ++) 28 { 29 scanf("%lf", &data[i]); 30 if (fabs(data[i]) < JD) 31 flag = 1; 32 } 33 if (data[1] >= 0) 34 { 35 ans[1][0] = data[1]; 36 ans[1][1] = FMAX; 37 } 38 else 39 { 40 ans[1][0] = ZMIN; 41 ans[1][1] = data[1]; 42 } 43 for (i = 2; i <= n; i ++) 44 if (data[i] >= 0) 45 { 46 if (fabs(ans[i - 1][0] - ZMIN) < JD || data[i] * ans[i - 1][0] < data[i]) 47 ans[i][0] = data[i]; 48 else 49 ans[i][0] = data[i] * ans[i - 1][0]; 50 if (fabs(ans[i - 1][1] - FMAX) < JD) 51 ans[i][1] = FMAX; 52 else 53 ans[i][1] = ans[i - 1][1] * data[i]; 54 } 55 else 56 { 57 if (fabs(ans[i - 1][0] - ZMIN) < JD || data[i] * ans[i - 1][0] > data[i]) 58 ans[i][1] = data[i]; 59 else 60 ans[i][1] = data[i] * ans[i - 1][0]; 61 if (fabs(ans[i - 1][1] - FMAX) < JD) 62 ans[i][0] = ZMIN; 63 else 64 ans[i][0] = ans[i - 1][1] * data[i]; 65 } 66 max = ans[1][0]; 67 for (i = 2; i <= n; i ++) 68 if (ans[i][0] > max) 69 max = ans[i][0]; 70 if (max > ZMIN) 71 { 72 if (fabs(max - (int)max) <= JD) 73 printf("%d\n", (int)max); 74 else 75 printf("%.2f\n", max); 76 } 77 else if (fabs(max) <= ZMIN && flag) 78 printf("0\n"); 79 else 80 printf("-1\n"); 81 } 82 return 0; 83 }
- 当i = 1时