有两堆牌,每张牌上有一个分值,每次取只能取其中一堆的头部或者尾部的牌,两个人轮流抽牌,采用最优策略,问先手最多能得到多少分。
题解:记忆化搜索。as和ae表示一堆的头和尾,bs和be表示另一堆的头和尾,f[as][ae][bs][be]表示当前状态下所能得到的最多分数。则f[as][ae][bs][be]等于当前所有分数和 - 下一状态的最多分数,按每种状态记忆化搜索下即可。
#include#include using namespace std; int dp[22][22][22][22]; int a[22],b[22]; int dfs(int x1,int y1,int x2,int y2) { int i,j,k,l; if(x1>y1&&x2>y2) { return dp[x1][y1][x2][y2]=0; // return 0; } if(dp[x1][y1][x2][y2]!=-1) return dp[x1][y1][x2][y2]; int s=0,tmp=0; if(x1<=y1) s+=a[y1]-a[x1-1]; if(x2<=y2) s+=b[y2]-b[x2-1]; if(x1<=y1) //四种不同的状态:#include #include
{ tmp=max(tmp,s-dfs(x1+1,y1,x2,y2)); tmp=max(tmp,s-dfs(x1,y1-1,x2,y2)); } if(x2<=y2) { tmp=max(tmp,s-dfs(x1,y1,x2+1,y2)); tmp=max(tmp,s-dfs(x1,y1,x2,y2-1)); } return dp[x1][y1][x2][y2]=tmp; // return tmp; } int sa[22],sb[22]; int main() { int i,j,k,l,n,m; int t; cin>>t; while(t--) { cin>>n; a[0]=b[0]=0; for(i=1;i<=n;i++) { cin>>a[i]; a[i]=a[i-1]+a[i]; } for(i=1;i<=n;i++) { cin>>b[i]; b[i]=b[i-1]+b[i]; } memset(dp,-1,sizeof(dp)); dfs(1,n,1,n); cout<<dp[1][n][1][n]<<endl; } }