题目链接:https://cn.vjudge.net/problem/HDU-4597 

Alice and Bob are playing a game. There are two piles of cards. There are N cards in each pile, and each card has a score. They take turns to pick up the top or bottom card from either pile, and the score of the card will be added to his total score. Alice and Bob are both clever enough, and will pick up cards to get as many scores as possible. Do you know how many scores can Alice get if he picks up first?

Input

The first line contains an integer T (T≤100), indicating the number of cases. 
Each case contains 3 lines. The first line is the N (N≤20). The second line contains N integer a i (1≤a i≤10000). The third line contains N integer b i (1≤bi≤10000).

Output

For each case, output an integer, indicating the most score Alice can get.

Sample Input

2 
 
1 
23 
53 
 
3 
10 100 20 
2 4 3 

Sample Output

53 
105 

题意:给定两个卡片序列,每张卡片都有一定的分数,Alice和Bob轮换从两个序列中拿卡片,每次只能从序列头部或尾部取走卡片。问Alice先取的话,最多可以取到的卡片分数和最多是多少。

dp[i][j][a][b]表示在第一个卡片子序列i-j,第二个卡片子序列a-b里,先取者最多可以得到的分数。

每一次最多有4种取法,无论哪一种成为了对方的先取最优选择了,用当前的sum减掉对方的最优选择,取四种中最大的就是自己的最优选择

记忆化搜索

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int num1[22],num2[22];
int sum1[22],sum2[22];
int dp[22][22][22][22];
int dfs(int i,int j,int a,int b){
	int sum=sum1[j]-sum1[i-1]+sum2[b]-sum2[a-1];
	if(dp[i][j][a][b]!=0) return dp[i][j][a][b];
	int ans=0;
	if(i<=j){
		ans=max(ans,sum-dfs(i+1,j,a,b)); 
		ans=max(ans,sum-dfs(i,j-1,a,b));
	}
	if(a<=b){
		ans=max(ans,sum-dfs(i,j,a+1,b));
		ans=max(ans,sum-dfs(i,j,a,b-1));
	}
	return dp[i][j][a][b]=ans;	
}
int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		memset(dp,0,sizeof(dp));
		int n;
		scanf("%d",&n);
		for(int i=1;i<=n;i++){
			scanf("%d",&num1[i]);
			sum1[i]=sum1[i-1]+num1[i];
		}
		for(int i=1;i<=n;i++){
			scanf("%d",&num2[i]);
			sum2[i]=sum2[i-1]+num2[i];
		}
		printf("%d\n",dfs(1,n,1,n));
	}
	return 0;
}