hdu 4597 记忆化搜索

有两堆牌,每张牌上有一个分值,每次取只能取其中一堆的头部或者尾部的牌,两个人轮流抽牌,采用最优策略,问先手最多能得到多少分。
题解:记忆化搜索。as和ae表示一堆的头和尾,bs和be表示另一堆的头和尾,f[as][ae][bs][be]表示当前状态下所能得到的最多分数。则f[as][ae][bs][be]等于当前所有分数和 - 下一状态的最多分数,按每种状态记忆化搜索下即可。


#include 
#include 
#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)        //四种不同的状态:
    {
        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;
    }

}


你可能感兴趣的:(动态规划)