1. 程式人生 > >Hdu4597---Play Game解題報告(記憶化搜尋)

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