题目链接:
题目描述:
给出一个数列,两人轮流取数, 取完结束。每次可以取好多个数,但是只能从首或者尾为起点取连续的若干个。问最后两者取数和的绝对值最大为多少?
解题思路:
区间dp,处理出来数列的前缀和,dp[l][r] 表示 区间 [l, r] 之间的数取完,两者取数和差值最大的值。枚举区间内点k,假设先手取[l, k] 或者 [k+1, r]取最大值,对剩下部分用先手取到的区间和减去就好,这样对于每一个区间都是先手先取,然后再枚举先手,子区间内的取法就要反一下咯。
1 #include <cmath> 2 #include <queue> 3 #include <cstdio> 4 #include <cstring> 5 #include <iostream> 6 #include <algorithm> 7 8 using namespace std; 9 typedef long long LL; 10 const int maxn = 110; 11 const int INF = 0x3f3f3f3f; 12 int dp[maxn][maxn], a[maxn]; 13 int main () 14 { 15 int T; 16 17 scanf ("%d", &T); 18 for (int t=1; t<=T; t++) 19 { 20 int n; 21 a[0] = 0; 22 scanf ("%d", &n); 23 memset (dp, 0, sizeof(dp)); 24 for (int i=1; i<=n; i++) 25 { 26 scanf ("%d", &a[i]); 27 dp[i][i] = a[i]; 28 a[i] += a[i-1]; 29 } 30 31 for (int i=2; i<=n; i++) 32 for (int l=1; l+i<=n+1; l++) 33 { 34 int r = l + i - 1; 35 dp[l][r] = a[r] - a[l-1]; 36 for (int k=l; k<r; k++) 37 { 38 int num = max(a[k]-a[l-1]-dp[k+1][r], a[r]-a[k]-dp[l][k]); 39 dp[l][r] = max (dp[l][r], num); 40 } 41 } 42 printf ("Case %d: %d ", t, dp[1][n]); 43 } 44 return 0; 45 }