题目大意:给你n个数,两个人轮流取,可以从左边开始去取连续的任意个,或者从右边取连续的任意个,

注意不能从两头取,所有的数都被取完游戏结束,输出先手与后手的分差;

解析:dp[i][j]   表示i~j区间内先手取的最大值,所以dp[1][n]表示的是取完所有数之后的最大值,

由于求的是最大值,所以给后手留下最小的,分两种情况,1.留给后手i+1~r区间;2.给后手留l~k区间

所以结果就是2*dp[i][j] - sum[n];

代码题解:

 

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
int a[maxn],sum[maxn],dp[102][102];
int n;
int vis[102][102];
int DP(int l,int r)
{
    if(vis[l][r])return dp[l][r];
    vis[l][r]=1;
    dp[l][r]=sum[r]-sum[l-1];
    for(int i=l;i<r;i++) //给后手留i+1~r区间
        dp[l][r]=max(dp[l][r],sum[r]-sum[l-1]-DP(i+1,r)); 
    for(int k=r-1;k>=l;k--)// 给后手留l~k区间
        dp[l][r]=max(dp[l][r],sum[r]-sum[l-1]-DP(l,k)); 
    return dp[l][r];
}
int main()
{

    while(scanf("%d",&n)&&n)
    {
        memset(vis,0,sizeof(vis));
        memset(dp,0,sizeof(dp));
        sum[0]=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            sum[i]=sum[i-1]+a[i];
        }
        printf("%d\n",2*DP(1,n)-sum[n]);
    }
    return 0;
}