参考博客 http://blog.csdn.net/zizaimengzhongyue/article/details/9413387                                                                             dfs http://blog.csdn.net/keyboarderqq/article/details/51878796
                                                                           *** http://www.bubuko.com/infodetail-788716.html

分析:
题目要求从两边取,权值为a[i]*cnt,这样就很不好处理。

假设从里面往外取,取最里面的那个权值为a[i]n,倒数第二个为a[j](n-1),

dp[i][j]表示取完[i,j]区间的最大值,那么由dp[i][i]很容易得到dp[i][i+1];

dp[i][j]=max(dp[i+1][j]+a[i]*cnt,dp[i][j-1]+a[j]*cnt); (cnt为第几次取数字)

最终答案就是dp[1][n];

题意:给出的一系列的数字,可以看成一个双向队列,每次只能从队首或者队尾出队,第n个出队就拿这个数乘以n,最后将和加起来,求最大和
code
:

#include<stdio.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<queue>
using namespace std;
#define ll long long
#define mem(a,t) memset(a,t,sizeof(a))
#define N 2005
const int M=100005;
const int inf=0x1f1f1f1f;
int a[N],dp[N][N];
int main()
{
    int i,j,k,n;
    while(~scanf("%d",&n))
    {
        mem(dp,0);
        for(i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);     //从里向外逆推区间
            dp[i][i]=a[i]*n;    //最后取的是a[i]
        }
        for(k=1;k<n;k++) //区间长度为k+1时
        {
            for(i=1;i+k<=n;i++)      //枚举区间长度为k+1的每个区间起点
            {
                j=i+k;               //该区间终点为j=i+k
                dp[i][j]=max(dp[i+1][j]+a[i]*(n-k),dp[i][j-1]+a[j]*(n-k));
            }            //该区间的最优解为先取左边或者右边两者的最大值
        }
        printf("%d\n",dp[1][n]);
    }
    return 0;
}