dp[ba][ta][bb][tb]表示a堆牌从下面拿了ba张,从上面拿了ta张。b堆牌从下面拿了bb张,从上面拿了tb张。当前玩家能得到的最大的分数。
扩展方式有4种,ba+1,ta+1,bb+1,tb+1,用当前剩下牌的总分减掉它,取最大值,就是当前玩家的最高分。
记忆化搜索
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> using namespace std; int a[30]; int b[30]; int sum; int dp[21][21][21][21],n,maxn; inline int cal_max(int a,int b,int c) { return max(max(a,b),c); } int dfs(int ba,int ta,int bb,int tb,int sums) { if(ba+ta==n&&bb+tb==n) return 0; if(dp[ba][ta][bb][tb]) return dp[ba][ta][bb][tb]; int maxn=0; if(ba+ta<n) { maxn=cal_max(maxn,sums-dfs(ba+1,ta,bb,tb,sums-a[ba+1]),sums-dfs(ba,ta+1,bb,tb,sums-a[n-ta])); } if(bb+tb<n) { maxn=cal_max(maxn,sums-dfs(ba,ta,bb+1,tb,sums-b[bb+1]),sums-dfs(ba,ta,bb,tb+1,sums-b[n-tb])); } dp[ba][ta][bb][tb]=maxn; return maxn; } int main() { int cas; scanf("%d",&cas); while(cas--) { sum=0; scanf("%d",&n); memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); sum+=a[i]; } for(int i=1;i<=n;i++) { scanf("%d",&b[i]); sum+=b[i]; } printf("%d\n",dfs(0,0,0,0,sum)); } return 0; }