Hdu4597---Play Game解题报告(记忆化搜索)

版权声明:转载请注明出处:https://blog.csdn.net/qq1013459920 https://blog.csdn.net/qq1013459920/article/details/83449665

                                       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;
}

猜你喜欢

转载自blog.csdn.net/qq1013459920/article/details/83449665
今日推荐