[NOIP模拟] Game
About
2017.10.29 T2
Solution :
这题与2017.10.11 T2 类似,复习此题时需要复习原T2。
我们定义 DP[i][j] 为当前还有 i 个(这里是到这来的,为什么?请自己思考),接下来会选 j 个的最坏情况的最优选取,注意是还没有选,于是我们可以得到DP的转移方程,在此之前请自己思考 :
DP[i][j]=max(−DP[i+j][j]+S(i, i+j),−DP[i+j+1][j+1]+S(i, i+j+1)
但当前取不到的情况 :
DP[i][j]=0(i+j>n and i<=n)
恰好满足 :
DP[i][j]=S(i, n)(i+j==n)
Code:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <ctime>
#include <map>
#include <vector>
using namespace std;
inline int read() {
int i = 0, f = 1;
char ch = getchar();
while(!isdigit(ch)) {
if(ch == '-') f = -1; ch = getchar();
}
while(isdigit(ch)) {
i = (i << 3) + (i << 1) + ch - '0'; ch = getchar();
}
return i * f;
}
const int MAXN = 2e4 + 5;
const int inf = 0x3f3f3f3f;
int dp[MAXN][205], sum[MAXN], n;
inline void init() {
for(int i = 1; i <= n; ++i)
for(int k = 0; k <= 200; ++k)
dp[i][k] = -inf, sum[i] = 0;
}
int main() {
freopen("1.in", "r", stdin);
int t = read();
while(t--) {
n = read();
init();
for(int i = 1; i <= n; ++i) sum[i] = sum[i - 1] + read();
for(int i = n; i >= 1; --i)
for(int k = 1; k <= 200; ++k) {
if(i + k > n) { if(i <= n) dp[i][k] = 0; }
else if(i + k == n) dp[i][k] = sum[n] - sum[i];
else {
dp[i][k] = max(dp[i][k], -dp[i + k][k] + sum[i + k] - sum[i]);
dp[i][k] = max(dp[i][k], -dp[i + k + 1][k + 1] + sum[i + k + 1] - sum[i]);
}
}
cout<<max(-dp[1][1] + sum[1], -dp[2][2] + sum[2])<<'\n';
}
}