题意:巨毒。。实际上就是A,B都希望自己得到的最多。前一个人拿k个,下一个人能拿k or k+1
思路:倒着DP。。实际上两个人是同一种策略,那么其实一个dp数组就可以了。。从最后一步拿k个往回推,dp[i][j]表示取第i个时候拿走包含i的j个,转移方程dp[i][j]=sum[i+j-1]-sum[i-1]-max(dp[i+j][j],dp[i+j][j+1]) (PS,注意一下边界的合法性判断),转移的时候要减去上一步的最优解。。因为每一步对手都会选择最优策略。。
PS。这个题卡空间。。。要么只开一个数组,要么循环滚动一下
代码:
#include<bits/stdc++.h>
#define MEM(x) memset(x,0,sizeof(x))
using namespace std;
int dp[22000][205],n,sum[22010],v[22010];
int main(){
int t;
scanf("%d", &t);
while (t--){
scanf("%d",&n);
sum[0]=0;
MEM(dp);MEM(sum);
for(int i=1;i<=n;++i)scanf("%d",&v[i]),sum[i]=sum[i-1]+v[i];
if(n==1){
printf("%d
",v[1]);
continue;
}
int lim = 200;
for(int i=n;i>=1;--i){
for(int j =1;j<=lim;++j){
if(i+j-1>n) break;
int sub=-2e9;
dp[i][j]=sum[i+j-1]-sum[i-1];
if(i+j+j-1<=n)sub=max(dp[i+j][j],sub);
if(i+j+j<=n)sub=max(dp[i+j][j+1],sub);
if(sub!=-2e9) dp[i][j]-=sub;
}
}
printf("%d
", max(dp[1][1],dp[1][2]));
}
return 0;
}