给定n个数字,A和B可以从这串数字的两端任意选数字,一次只能从一端选取。两人都采用最优策略,A先手,问A和B各自得到数字的和的差值最大为多少?
区间DP
F[i][j]表示区间i~j内A能得到的最大数字和。
1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<vector> 8 using namespace std; 9 const int mxn=110; 10 int read(){ 11 int x=0,f=1;char ch=getchar(); 12 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 13 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 14 return x*f; 15 } 16 int a[mxn]; 17 int sum[mxn],L[mxn][mxn],R[mxn][mxn]; 18 int f[mxn][mxn]; 19 int n; 20 void solve(){ 21 int i,j; 22 for(i=1;i<=n;i++){ 23 f[i][i]=L[i][i]=R[i][i]=a[i]; 24 } 25 for(int st=2;st<=n;st++){ 26 for(i=1;i<=n-st+1;i++){ 27 j=i+st-1; 28 f[i][j]=sum[j]-sum[i-1]-min(min(L[i+1][j],0),R[i][j-1]); 29 L[i][j]=min(f[i][j],L[i+1][j]); 30 R[i][j]=min(f[i][j],R[i][j-1]); 31 } 32 } 33 printf("%d ",f[1][n]-(sum[n]-f[1][n])); 34 return; 35 } 36 int main(){ 37 int i,j; 38 while(scanf("%d",&n) && n){ 39 for(i=1;i<=n;i++)a[i]=read(); 40 memset(f,0,sizeof f); 41 memset(L,0x3f,sizeof L); 42 memset(R,0x3f,sizeof R); 43 for(i=1;i<=n;i++)sum[i]=sum[i-1]+a[i]; 44 solve(); 45 } 46 return 0; 47 }