UVa10891 Game of Sum

给定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 }
原文地址:https://www.cnblogs.com/SilverNebula/p/6575454.html