我可能真想不到这题是区间DP,不过知道是区间DP想了下就AC了。
dp[i][j]表示局面为ai...aj先手能获得与后手得分的最大差值
那么转移到当前状态就是枚举中间的位置,分成两边,其中一边先手全部取另一边就是新的局面,后手变成新的先手的局面,而后手也会采取最优策略也会尽量让剩下这个局面差值最大。方程如下:
dp[i][j] = max( sum[i][j] , sum[i][k]-dp[k+1][j] , sum[k+1][j]-dp[i][k] ) (i<=k<j)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 #define INF (1<<29) 6 int d[111][111]; 7 int main(){ 8 int t,n,s[111]={0}; 9 scanf("%d",&t); 10 for(int cse=1; cse<=t; ++cse){ 11 scanf("%d",&n); 12 for(int i=1; i<=n; ++i) scanf("%d",s+i),s[i]+=s[i-1]; 13 for(int i=1; i<=n; ++i){ 14 for(int j=1; j<=n; ++j) d[i][j]=-INF; 15 d[i][i]=s[i]-s[i-1]; 16 } 17 for(int len=1; len<n; ++len){ 18 for(int i=1; i+len<=n; ++i){ 19 d[i][i+len]=s[i+len]-s[i-1]; 20 for(int j=i; j<i+len; ++j) d[i][i+len]=max(d[i][i+len],s[j]-s[i-1]-d[j+1][i+len]); 21 for(int j=i+len; j>i; --j) d[i][i+len]=max(d[i][i+len],s[i+len]-s[j-1]-d[i][j-1]); 22 } 23 } 24 printf("Case %d: %d\n",cse,d[1][n]); 25 } 26 return 0; 27 }