Maximum Energy <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
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 – 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。
转载于:https://blog.51cto.com/williamwhe/156703