这是区域赛的一道题目,感觉还是很难,做了好久都没想法,然后看了解题
区间dp,dp[a1][a2][b1][b2]表示在这两个区间内,先后所能获得的最大值,然后就是状态转移,有四种可能,以取a堆最左边的那个数字为例,状态转移方程如下:
dp[a1][a2][b1][b2] = max(dp[a1][a2][b1][b2],a[a1+1]+suma[a2-1]-suma[a1+1]+sumb[b2-1]-sumb[b1]-dfs(a1+1,a2,b1,b2));
数组的含义看代码注释,-法后手的东西表示后首在先手完成的情况下实现的最大价值
#include<iostream>
#include<algorithm>
#include<cstring>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<time.h>
#include<math.h>
#define N 25
#define inf 0x7fffffff
#define eps 1e-9
#define pi acos(-1.0)
#define P system("pause")
using namespace std;
int a[N],b[N];//a,b记录输入数组
int suma[N],sumb[N];//记录前i个数之后
int dp[N][N][N][N];//第一堆代表区间a1到a2,第一堆b1到b2
int dfs(int a1,int a2,int b1,int b2)
{
if(dp[a1][a2][b1][b2] != -1) return dp[a1][a2][b1][b2];
dp[a1][a2][b1][b2] = 0;
if(a1+1 < a2)
dp[a1][a2][b1][b2] = max(dp[a1][a2][b1][b2],a[a1+1]+suma[a2-1]-suma[a1+1]+sumb[b2-1]-sumb[b1]-dfs(a1+1,a2,b1,b2));
if(a1 < a2-1)
dp[a1][a2][b1][b2] = max(dp[a1][a2][b1][b2],a[a2-1]+suma[a2-2]-suma[a1]+sumb[b2-1]-sumb[b1]-dfs(a1,a2-1,b1,b2));
if(b1+1 < b2)
dp[a1][a2][b1][b2] = max(dp[a1][a2][b1][b2],b[b1+1]+suma[a2-1]-suma[a1]+sumb[b2-1]-sumb[b1+1]-dfs(a1,a2,b1+1,b2));
if(b1 < b2-1)
dp[a1][a2][b1][b2] = max(dp[a1][a2][b1][b2],b[b2-1]+suma[a2-1]-suma[a1]+sumb[b2-2]-sumb[b1]-dfs(a1,a2,b1,b2-1));
return dp[a1][a2][b1][b2];
}
int main()
{
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
int i,j;
suma[0] = 0;
for(i = 1; i <= n; i++){
scanf("%d",&a[i]);
suma[i] = suma[i-1] + a[i];
}
sumb[0] = 0;
for(i = 1; i <= n; i++)
{
scanf("%d",&b[i]);
sumb[i] = sumb[i-1] + b[i];
}
memset(dp,-1,sizeof(dp));
dfs(0,n+1,0,n+1);
printf("%d\n",dp[0][n+1][0][n+1]);
}
return 0;
}