Jumping Cows解题报告

Description

Farmer John's cows would like to jump over the moon, just like the cows in their favorite nursery rhyme. Unfortunately, cows can not jump.

The local witch doctor has mixed up P (1 <= P <= 150,000) potions to aid the cows in their quest to jump. These potions must be administered exactly in the order they were created, though some may be skipped.

Each potion has a 'strength' (1 <= strength <= 500) that enhances the cows' jumping ability. Taking a potion during an odd time step increases the cows' jump; taking a potion during an even time step decreases the jump. Before taking any potions the cows' jumping ability is, of course, 0.

No potion can be taken twice, and once the cow has begun taking potions, one potion must be taken during each time step, starting at time 1. One or more potions may be skipped in each turn.

Determine which potions to take to get the highest jump.

Input

* Line 1: A single integer, P

* Lines 2..P+1: Each line contains a single integer that is the strength of a potion. Line 2 gives the strength of the first potion; line 3 gives the strength of the second potion; and so on.

Output

* Line 1: A single integer that is the maximum possible jump.

Sample Input

8
7
2
1
8
4
3
5
6

 

Sample Output

17

解法或类型:贪心

解题思路:题目要求从输入的p个数中任意选出n(n<=p)个数按输入顺序排好,假设给n个数1N编号,

i(1<=i<=N)是偶数,则将第i个数变为负数,最后求n个数的最大和。乍看之下,一头雾水,那么首先

就先大概确定一下这道题的类型,一般来说,求极值、最值优先考虑贪心、动态规划。先来看看动态

规划的可能性高不高:p最大为6位数,而一般动归的复杂度为O(p^2),显然超时,就算能优化O(p*log(p))

可是稍微想一下,它的状态递推关系及其复杂,所以动归的可能性几乎为0%。这下好了,只剩贪心了,

我手工模拟了一下p1234的几种情况,当p=5时,就几乎没法下手了,看来这贪法不行,正在

苦思冥想中,突然想到了任意选出来的n个数中,最后一个数肯定为正,这是一种贪,我想能不能从后往

前贪,最终还是回到了原点,因为第一个数也肯定为正。但确是这种思路给了我一个灵感:好,把所有

确定因素都记下来,省的在脑海里盘旋。很快我就想到了一个:最大的数一定为正接着想从最大的数

开始贪,要是能贪一边,那另一边也不成问题了。一边的话那么至少选两个数,而且小的在前,这样相

减才会大于零,很快地,就联想到了最长递增连续子序列。那么从这里面肯定要选偶数个,想了好多弯

路后,才发现首尾相减肯定比里面添几对数要大。所以只要一直选最长递增连续子序列,直到选完为止

就可以了。这样复杂度为O(p),肯定满足题目要求了。

总结:有时候没思路时,可以把一些确定因素记下来,没准会有用或者启发你的灵感;另外使用贪心

时,它可能会会从某一点开始贪。还有若做这题时,我不能静下冷静思考,我是万万做不出的。

程序代码:

#include <iostream> using namespace std; int n; int h[150010]; int max, p, sum, begin, end; int main() { while( scanf("%d", &n)!=EOF ) { int i; //保存最大的数和它的下标 max = 0; for( i=1; i<=n; ++i ) { scanf("%d", &h[i]); if( max<h[i] ) { max = h[i]; p = i; } } //最大的数肯定要选 sum = max; //在最大数左边寻找所有递增子序列,首尾元素之差加到sum中去 i = p+2; while( i<=n ) { if( h[i-1]<h[i] ) { begin = i-1; i++; while( i<=n ) { if( h[i-1]>=h[i] ) break; i++; } end = i-1; sum += h[end]-h[begin]; } i++; } //同上,但从最大数右边开始寻找 i = p-2; while( i>=1 ) { if( h[i]>h[i+1] ) { begin = i+1; i--; while( i>=1 ) { if( h[i+1]>=h[i] ) break; i--; } end = i+1; sum += h[end] - h[begin]; } i--; } printf("%d/n", sum); } return 0; }

你可能感兴趣的:(优化,Integer,input,each,output,联想)