hdu4597Play Game 记忆化搜索

//两堆数量为n(n<=20) 的牌,每个牌都有份数
//两个人轮流拿牌,可以取两堆数的头或者尾中的一张
//每个人都取最优解
//问第一个人能够取得的最大分数
//记忆化搜索 dp[sa][ta][sb][tb]  表示第一堆剩下sa,ta,第二堆剩下
//sb,tb的最大值
#include
#include
#include
using namespace std ;
const int maxn = 21;
int dp[maxn][maxn][maxn][maxn] ;
int a[maxn], b[maxn] ;
int ss ;
int dfs(int sa ,int ta , int sb,int tb, int res)
{
    if(sa > ta && sb > tb)
    return 0 ;
    if(dp[sa][ta][sb][tb] != -1)
    return dp[sa][ta][sb][tb] ;
    int ans = 0 ;
    int tmp = 0 ;
    if(sa <= ta){
        ans = max(ans , res-dfs(sa+1,ta,sb,tb,res-a[sa])) ;
        ans = max(ans , res-dfs(sa,ta-1,sb,tb,res-a[ta])) ;
    }
    if(sb <= tb){
        ans = max(ans , res-dfs(sa,ta,sb+1,tb,res-b[sb])) ;
        ans = max(ans , res-dfs(sa,ta,sb,tb-1,res-b[tb])) ;
    }
    dp[sa][ta][sb][tb] = ans ;
    return ans ;
}
int main()
{
    int t ;
    scanf("%d" , &t) ;
    while(t--)
    {
        int n ;
        scanf("%d" , &n) ;
        int sum  = 0 ;
        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] ;
        }
        memset(dp,-1,sizeof(dp)) ;
        printf("%d\n" ,  dfs(1,n,1,n,sum)) ;
    }
}

你可能感兴趣的:(搜索)