题意:给定两串长度均为n的数列,两个人轮流取数,可以取两串数列的头或尾元素,求先取者能获得的最大值。
明显的四维区间dp,相当于取数游戏的升级版,由小区间拓展到大区间即可。
#include<iostream> #include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #define FOR(i,x,y) for(int i=(x);i<=(y);i++) #define DOR(i,x,y) for(int i=(x);i>=(y);i--) using namespace std; int dp[23][23][23][23]; int a[23],b[23]; int sa[23],sb[23]; int suma(int x,int y) { return sa[y]-sa[x-1]; } int sumb(int x,int y) { return sb[y]-sb[x-1]; } int main() { int T; scanf("%d",&T); while(T--) { memset(dp,0,sizeof(dp)); int n; scanf("%d",&n); FOR(i,1,n) { scanf("%d",&a[i]); sa[i]=sa[i-1]+a[i]; } FOR(i,1,n) { scanf("%d",&b[i]); sb[i]=sb[i-1]+b[i]; } FOR(l1,0,n)FOR(l2,0,n) //枚举两堆卡片被取的张数 FOR(L1,1,n-l1+1)FOR(L2,1,n-l2+1) //枚举两堆卡片左端点 { int R1=L1+l1-1,R2=L2+l2-1; if(l1)dp[L1][R1][L2][R2]=max(dp[L1][R1][L2][R2],suma(L1,R1)+sumb(L2,R2)-min(dp[L1+1][R1][L2][R2],dp[L1][R1-1][L2][R2])); if(l2)dp[L1][R1][L2][R2]=max(dp[L1][R1][L2][R2],suma(L1,R1)+sumb(L2,R2)-min(dp[L1][R1][L2+1][R2],dp[L1][R1][L2][R2-1])); } printf("%d\n",dp[1][n][1][n]); } return 0; }