HDU 4597 Play Game (记忆化搜索)

                                               Play Game

Problem Description

Alice and Bob are playing a game. There are two piles of cards. There are N cards in each pile, and each card has a score. They take turns to pick up the top or bottom card from either pile, and the score of the card will be added to his total score. Alice and Bob are both clever enough, and will pick up cards to get as many scores as possible. Do you know how many scores can Alice get if he picks up first?

Input

The first line contains an integer T (T≤100), indicating the number of cases. 
Each case contains 3 lines. The first line is the N (N≤20). The second line contains N integer ai (1≤ai≤10000). The third line contains N integer bi (1≤bi≤10000).

Output

For each case, output an integer, indicating the most score Alice can get.

题目意思:

两堆卡片,每堆N张卡片,两堆的N张卡片对于n个值ai,bi,每次取卡片只能从堆顶或堆底选择,Alice和Bob轮流选取卡片,并获得卡片面值。

求Alice先手,取卡片能够获得的最大值。

解题思路:

记忆化搜索,其实说白了就是暴搜+动态规划,每次搜索过程中记录一些状态的值,下次搜索过程中如果再次经历这个状态,则直接调用,减少重复搜索量。

s1代表第一堆卡片堆顶位置,e1代表第一堆卡片堆底位置,s2,e2对第二堆同理...

dfs搜索的是Bob取卡片的值,所以我们要取最小。

dp[MAX_N][MAX_N][MAX_N][MAX_N]记录的是每次搜索Alice取卡片的最大值。

AC Code:

#include<iostream>
#include<sstream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<map>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<list>
#define mod 998244353
#define INF 0x3f3f3f3f
#define Min 0xc0c0c0c0
#define mst(a) memset(a,0,sizeof(a))
#define f(i,a,b) for(int i = a; i < b; i++)
using namespace std;
typedef long long ll;
const int MAX_N = 25;
int len, ans;
int dp[MAX_N][MAX_N][MAX_N][MAX_N];
int a[MAX_N], b[MAX_N];
int dfs(int s1, int e1, int s2, int e2, int sum){   //dfs搜索Bob获取的卡片值,sum代表所有卡片剩余总面值
    if(dp[s1][e1][s2][e2]){                          //之前搜索过的状态,直接返回值
        return dp[s1][e1][s2][e2];
    }
    if(s1 > e1 && s2 > e2){
        return 0;
    }
    int res = -9999;
    if(s1 <= e1){
        int tmp = max(sum - dfs(s1 + 1, e1, s2, e2, sum - a[s1]), sum - dfs(s1, e1 - 1, s2, e2, sum - a[e1]));
        res = max(res, tmp);
    }
    if(s2 <= e2){
        int tmp = max(sum - dfs(s1, e1, s2 + 1, e2, sum - b[s2]), sum - dfs(s1, e1, s2, e2 - 1, sum - b[e2]));
        res = max(res, tmp);             //取dfs搜索Bob的获取卡片值的最小值
    }
    return dp[s1][e1][s2][e2] = res;      //返回Alice取卡片最大值
}
int main(){
    ios::sync_with_stdio(false);
    int T, n, sum;
    cin>>T;
    while(T--){
        sum = 0;
        mst(a), mst(b), mst(dp);
        cin>>n;
        for(int i = 1; i <= n; i++){
            cin>>a[i];
            sum += a[i];
        }
        for(int i = 1; i <= n; i++){
            cin>>b[i];
            sum += b[i];
        }
        ans = dfs(1, n, 1, n, sum);
        cout<<ans<<endl;
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值