A Game(区间DP)

Little Hi and Little Ho are playing a game. There is an integer array in front of them. They take turns (Little Ho goes first) to select a number from either the beginning or the end of the array. The number will be added to the selecter's score and then be removed from the array.

Given the array what is the maximum score Little Ho can get? Note that Little Hi is smart and he always uses the optimal strategy.

Input

The first line contains an integer N denoting the length of the array. (1 ≤ N ≤ 1000)

The second line contains N integers A1, A2, ... AN, denoting the array. (-1000 ≤ Ai ≤ 1000)

Output

Output the maximum score Little Ho can get.

Sample Input

4
-1 0 100 2

Sample Output

99

官方题解 http://hihocoder.com/discuss/question/4984
 1 /*
 2 问题 两人轮流从一个数组的头或者尾选择一个数累加,并且将其删除,问先手累加的数最大是能多少
 3 抽象问题 由于每次只能从数组首/尾拿走一个数,所以小Hi和小Ho在任何时候面对的残局都只可能是一段连续的子数组A[i..j]。
 4 变量 i j 最多能获得的得分,其中i,j表示区间端点下标 
 5 定义状态 我们不妨用f[i][j]表示当面对A[i..j],先手最多能获得的得分。
 6 并且如果我们能计算出所有f[i][j]的值,那么显然f[1][n]就是最终答案。
 7 状态转移 
 8 i=j时,f[i][j]=A[i];
 9 i<j时,此时先手面临A[i...j],若取A[i],则后手面临A[i+1...j],最多能得f[i+1][j]分,那么先手当前得分为 
10 区间和减去后手最多得分(其实此时的后手也是先手,因为都符合每次都作出最优选择的条件) 
11 即sum(A[i...j]) - f[i+1][j];
12 同理,若先手取A[j],则为sum(A[i...j]) - f[i][j-1];
13 
14 接下来就是写代码了(废话),我想说的是,状态方程虽然列出来了,怎么用也是需要思考的
15 我的做法是推理,要想计算f[i][j]需要先计算f[i+1][j]和f[i][j-1]
16 容易看出,i需要递减循环,j需要递增循环
17 故得出代码如下 
18 */ 
19 #include<stdio.h>
20 int max(int x, int y){
21     return x > y ? x : y;
22 }
23 int min(int x, int y){
24     return x > y ? y : x;
25 }
26 int n,A[1010],sum[1010],f[1010][1010];//大数组开成全局 
27 int main()
28 {
29     int i,j;
30     while(scanf("%d",&n) != EOF)
31     {
32         sum[0]=0;
33         for(i=1;i<=n;i++){
34             scanf("%d",&A[i]);
35             sum[i] = sum[i-1] + A[i];
36         }
37         for(i=n;i>=1;i--){
38             for(j=1;j<=n;j++){
39                 if(i == j)
40                 f[i][j]=A[i];
41                 else if(i < j)
42                 f[i][j]=sum[j] - sum[i-1] - min(f[i+1][j],f[i][j-1]);
43                 //f[i][j]=max(sum[j]-sum[i-1] - f[i+1][j],sum[j]-sum[i-1] - f[i][j-1]);
44                 //i > j无需处理 
45             }
46         }
47         printf("%d\n",f[1][n]); 
48     }
49     return 0;
50  } 

 


 

posted @ 2018-02-12 14:08  Reqaw  阅读(205)  评论(0编辑  收藏  举报