# gems gems gems

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1172    Accepted Submission(s): 242

Problem Description
Now there are n gems, each of which has its own value. Alice and Bob play a game with these n gems.
They place the gems in a row and decide to take turns to take gems from left to right.
Alice goes first and takes 1 or 2 gems from the left. After that, on each turn a player can take k or k+1 gems if the other player takes k gems in the previous turn. The game ends when there are no gems left or the current player can't take k or k+1 gems.
Your task is to determine the difference between the total value of gems Alice took and Bob took. Assume both players play optimally. Alice wants to maximize the difference while Bob wants to minimize it.

Input
The first line contains an integer T (1T10), the number of the test cases.
For each test case:
the first line contains a numbers n (1n20000);
the second line contains n numbers: V1,V2Vn. (100000Vi100000)

Output
For each test case, print a single number in a line: the difference between the total value of gems Alice took and the total value of gems Bob took.

Sample Input
1 3 1 3 2

Sample Output
4

Source

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
#define MS(x, y) memset(x, y, sizeof(x))
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }
const int N = 2e4 + 10, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f;
template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }
int casenum, casei;
int n;
int sum[N];
int v[N];
int f[N][202];
int main()
{
scanf("%d", &casenum);
for (casei = 1; casei <= casenum; ++casei)
{
scanf("%d", &n);
for (int i = n; i >= 1; --i)scanf("%d", &v[i]);
for (int i = 1; i <= n; ++i)sum[i] = sum[i - 1] + v[i];

//设m为最大能取到的数量，则有(1+m)*m<=n*2，得到m^2+m<=n*2，得到m<sqrt(n*2)
int m = sqrt(n * 2);
while ((1 + m) * m > n * 2)--m;

for (int i = 1; i <= n; ++i)//枚举当前还剩下几个
{
int top = min(i, m);
for (int j = 1; j <= top; ++j)//枚举上一轮的人拿了多少个
{
f[i][j] = -2e9;
gmax(f[i][j], (sum[i] - sum[i - j]) - f[i - j][j]);							//这一轮拿一样多
if(i > j)gmax(f[i][j], (sum[i] - sum[i - j - 1]) - f[i - j - 1][j + 1]);	//这一轮多拿一个
}
}
printf("%d\n", f[n][1]);
}
return 0;
}
/*
【题意】

【分析】

1，所有非法状态，都以0为初始值即可
2，每个v最多使得绝对值偏差1e5，所以int即可保存所有状态

【时间复杂度&&优化】
O(nsqrt(n))

*/

#### 2017 ACM/ICPC Asia Regional Shenyang Online【solved：7 / 12】

2017-09-11 09:04:06

#### HDU 6199 gems gems gems （DP, 2017 ACM/ICPC Asia Regional Shenyang Online）

2017-09-11 09:01:14

#### 2017 ACM/ICPC Asia Regional Qingdao Online【solved：7 / 11】

2017-09-17 20:40:53

#### HDU 5476 Explore Track of Point 几何题 —— 2015 ACM/ICPC Asia Regional Shanghai Online

2015-09-26 19:06:18

#### 2015 ACM/ICPC Asia Regional Changchun Online (部分)

2015-09-20 20:56:06

#### HDU-2017 ACM/ICPC Asia Regional Qingdao Online-补题

2017-09-19 00:49:53

#### Asia Regional Contest 第35届ACM/ICPC亚洲赛区

2010-05-09 22:57:00

#### 「备战PKUWC2018」2017-2018 ACM-ICPC, Asia Daejeon Regional Contest

2018-01-16 21:20:50

#### The 36th ACM/ICPC Asia Regional Shanghai Site —— Warmup hdu 4016 Magic Bitwise And Operation

2011-09-09 13:00:43

#### 2017 ACM ICPC Asia Regional - Daejeon Programming Constest

2018-03-31 20:59:40