一道动态规划算法题

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

你可能感兴趣的:(算法,职场,动态规划,休闲)