Lightoj 1031 - Easy Game (区间DP)

题目链接:

  Lightoj  1031 - Easy Game

题目描述:

  给出一个数列,两人轮流取数, 取完结束。每次可以取好多个数,但是只能从首或者尾为起点取连续的若干个。问最后两者取数和的绝对值最大为多少?

解题思路:

  区间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\n", t, dp[1][n]);
43     }
44     return 0;
45 }

 

posted @ 2015-11-12 09:59  罗茜  阅读(411)  评论(0编辑  收藏  举报