题目链接:HDU 6199
1 3 1 3 2
4
题目分析:比赛时被博弈的思想套住了,既然找不到必胜必负态自然也无法找规律或者sg函数,实际上是dp的题,dp[i][j][k] 代表第i个人从第j个开始取,可取的是k或k+1。i取0或1,j取20000,k的最大值是sqrt(n*2)<=200,状态转移方程是dp[0][i][j]=区间和[i~i+j-1]+max(dp[1][i+j][j],dp[1][i+j+1][j+1]+s[i+j])对于另一个人也是一样,然后注意有时取不到k+1,之后网上get到的每次只会影响k区间范围的数,所以滚动数组即可,滚动的大小比k最大值大即可,这里取256,%256可以用&255来优化。
//
// main.cpp
// gems gems gems
//
// Created by teddywang on 2017/09/10.
// Copyright © 2017年 teddywang. All rights reserved.
//
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int T;
int dp[2][300][300];
int n;
int s[21001],pre[21001];
int mod=255;
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
memset(dp,0,sizeof(dp));
pre[0]=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&s[i]);
pre[i]=pre[i-1]+s[i];
}
int size=sqrt(n*2)+1;
for(int i=n;i>=1;i--)
{
for(int j=size;j>=1;j--)
{
if(i+j<=n)
{
dp[0][i&mod][j]=pre[(i+j-1)]-pre[i-1]+max(dp[1][(i+j)&mod][j],dp[1][(i+j+1)&mod][j+1]+s[i+j]);
dp[1][i&mod][j]=-pre[i+j-1]+pre[i-1]+min(dp[0][(i+j)&mod][j],dp[0][(i+j+1)&mod][j+1]-s[i+j]);
}
else if(i+j==n+1)
{
dp[0][i&mod][j]=pre[i+j-1]-pre[i-1]+dp[1][(i+j)&mod][j];
dp[1][i&mod][j]=pre[i-1]-pre[i+j-1]+dp[0][(i+j)&mod][j];
}
}
}
printf("%d\n",dp[0][1][1]);
}
}