设dp[i][j]为i->j第一个去的人所能的到的最大和,则A能去的的最大和为dp[1][n],B的和为sum[i->j]-dp[i][n]。
dp[i][j]=sum[i->j]-min{dp[i+1...j][j],dp[i][j-1.....i],0},由于共有n*n个状态,而每个状态有i..j种转移,O(N^3)。
然而是可以把复杂度降为O(n^2)的,由于每次状态转移的时候,都要去找i->j种哪个状态的值最小,如果能够
记录i->j的最小值,就不用每次都去遍历了。从O(N)变为了O(1)。用f[i][j]=min{dp[i][j],f[i+1][j]},g[i][j]=min{dp[i][j],g[i][j-1]}
。如果是求最大也是可以的。对于给定的一个序列同样适用。
代码:
/*
uva 10891
*/
#include <stdio.h>
#include <algorithm>
#include <string.h>
#define max 110
int min(int a,int b)
{
if(a>b)
return b;
return a;
}
int main(int argc, char const *argv[])
{
// freopen("input","r",stdin);
int n;
while(scanf("%d",&n),n)
{
int a[max];
int sum[max]={0};
for (int i = 1; i <=n; ++i)
{
scanf("%d",&a[i]);
sum[i]=sum[i-1]+a[i];
}
int dp[max][max],f[max][max],g[max][max];
memset(dp,false,sizeof(dp));
memset(f,false,sizeof(f));
memset(g,false,sizeof(g));
for(int i=1;i<=n;i++) dp[i][i]=f[i][i]=g[i][i]=a[i];
for(int l=1;l< n;l++)//不能按i从n-1,j从1-n
for(int i=1;i<=n;i++)
{
int j=i+l;
dp[i][j]=sum[j]-sum[i-1]-min(min(f[i+1][j],g[i][j-1]),0);
f[i][j]=min(dp[i][j],f[i+1][j]);
g[i][j]=min(dp[i][j],g[i][j-1]);
}
printf("%d\n",2*dp[1][n]-sum[n]);
}
return 0;
}