Maximum Energy
Time Limit:1000MS Memory Limit:32768K
Description:
Bob wanted to increase his energy by eating AC-APPLEs. There are N(1 <= N <= 150,000) AC-APPLEs, each AC-APPLE had a magic value "v" which is a positive interger and not bigger than 500. Bob visited AC-APPLEs which are given in order, every time he faced an AC-APPLE, he can choose "eat this one" or "pass this one". The odd time Bob ate, he increase v units energy. The even time Bob ate, he decrease v units energy. Before eating any AC-APPLE, Bob's enerny is 0. Please calculate the Maximum Energy Bob can increase by eating AC-APPLEs.
Input:
The input will consist of more than one data set. Each data set has two lines. First line has an interger N. Second line has N intergers which means the magic value of each AC-APPLEs.
Output:
the Maximum Energy Bob can increase
Sample Input:
8
7 2 1 8 4 3 5 6
Sample Output:
17
问题是这样的,以
7 2 1 8 4 3 5 6
为例,如果选择
+7
,则下一个数字则是
-
,比如
+7,-2
。你也可以选择跳过,比如
+7,-1
,这样就跳过
2
。总之加之后必定是减,加减交错。或者选择跳过。最后让你求经过这样的运算,一串数最终能得到的最大值。
本例中,最大值
17
是这么算出来的:
7-1+8-3+6=17
,中间跳过了
2
,
4
和
5
。这道题如果用穷举法来做自然可以,算法效率为
O(2^N)
,因为每个数字上的选择只有
2
种:
1)
加
/
减
2)
跳过
然后在所有
2^N
个结果中选择最大值即可。
但是
N
的最大值是
150000
,这种情况下,
O(2^N)
的效率显然无法接受。这道题可以分解成好几个子问题,于是我们可以用动态规划算法来实现算法性能的改进,使算法效率压缩到
O(N)
。
我们知道,当计算到最后一个数
6
时,对其采取加
/
减或是跳过,完全取决于对
7 2 1 8 4 3 5
子序列的计算结果。
仔细归纳一下,不外乎
4
种情况:
1
)如果前面的
5
是加的话,
6
自然是减
2
)如果前面的
5
是减的话,后面的
6
自然是加
3
)如果前面的
5
是跳过的话,那就直到找到从
5
开始往左数,第一个不跳过的数,比如是
8
(假如
4
,
3
,
5
都跳过)
a)
如果
8
是加,则
6
减,类似情况
1)
b)
如果
8
是减,则
6
加,类似情况
2)
而对于
1)
和
3a)
来说,对
6
的处理是一样的,唯一不同的是计算到
5
和计算到
8
时的最大值是不一样的。所以我们只需要找到
2
者中的最大值进行处理,这样
1)
和
3)
这两种情况可以归并为一种。同理,
2),3b)
也归并为一种。
还是以
7 2 1 8 4 3 5 6
为例,
我们可以基于刚才的算法给出如下表:
其中
add[index=1]=0
,表示下一次
0
将加上
2
,或者跳过
2
;
sub[index=1]=7
,表示下一次,
7
将减去
2
或者跳过
2
。
当遍历到
2
时,我们罗列出以下
4
种情况:
1) 7 �C 2 = 5 (
后面是
add)
2) 7
跳过
2 = 7 (
后面继续是
sub)
3) 0 + 2 = 2 (
后面是
sub)
4) 0
跳过
2 = 0 (
后面继续是
add)
1)
和
4)
后面都是
+
,而
1)
的当前值是
5
,
4)
却是
0
,这里我们要舍弃
4)
,选择方案
1)
。同理,对于
2)
和
3)
,后面都是
-
,而
2)
的当前值是
7
,大于
3)
的当前值
2
,所以舍弃方案
3)
。保留下来的是
1)
和
2)
,于是表变成了:
如果把行
“+”
用
add[]
存储,把行
“-”
用
sub[]
存储,
7 2 1 8 ……
表示为
NUM[]
,我们可以将其公式化为:
add[i] = max(sub[i-1]-NUM[i], add[i-1]) i)
sub[i] = max(sub[i-1], add[i-1]+NUM[i]) ii)
有了公式
i)
和
ii)
,我们就可以将后面的表格填写完全,最终的表格为:
因为
add[i] > add[i-1]
,且
sub[i] > sub[i-1]
,所以最后的最大值一定是
add[N]
和
sub[N]
中的一个。所以
max(11,17) = 17
。