最大连续子序列乘积(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 }
View Code
 
posted @ 2013-07-25 10:39  在于思考  阅读(1203)  评论(1编辑  收藏  举报