J - Boxes Game Gym - 101502J 记忆化搜索+博弈

J. Boxes Game

time limit per test

3.0 s

memory limit per test

256 MB

input

standard input

output

standard output

Ibraheem and Husam are playing a game with group of boxes, lined next to each other on a straight line, such that each box contains a card with some value written on it. Ibraheem and Husam already know the values of all cards before the game starts.

Ibraheem and Husam take turns to play the game, Ibraheem starts first. In each turn, a player can take one box from either ends of the line, add the value of the card inside this box to his score, then remove this box from the line.

Knowing that both players play optimally, your task is to calculate the value x - y, such that x is Ibraheem's score at the end of the game, and y is Husam's score at the end of the game.

Input

The first line contains an integer T (1 ≤ T ≤ 500), where T is the number of test cases.

The first line of each test case contains an integer n (1 ≤ n ≤ 103), where n is the number of boxes in the line.

The second line of each test case contains n integers a1, a2, ..., an ( - 103 ≤ ai ≤ 103), giving the values of the cards inside the boxes.

Output

For each test case, print a single line containing its answer.

Example

input

5
4
3 1 100 5
1
1000
4
-1 100 4 -5
1
-4
1
0

output

97
1000
92
-4
0

题意:

Ibraheem 和 Husam两人玩游戏,给你一串数,两人只能从两端开始取牌,拿到的数将加在自己的得分里,两个人都希望自己的分数尽可能的大并且采取最优策略,Ibraheem先取,得分为x,Husam得分为y,问最后x-y等于多少。

做法:dp[x][y]表示此人在区间[x, y]能取得的最大分数。这个人取完,另一个人也采取相同策略,当一个人在[x, y]区间两端取走一个数,那么另一人将面临两个状态[x+1, y]和[x, y-1],第一个人想要取得最大值,一定会想让另个人取这两种状态中的较小值。设[x][y]区间的数字和为all,转移方程就是dp[x][y] = max{all - dp[x+1][y]),all- dp[x][y-1])}。


代码1:时间较少

#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
int dp[1005][1005],vis[1005][1005],a[1005],sum[1005];
int dfs(int l,int r){
    if(vis[l][r]) return dp[l][r];
    else if(l==r) return dp[l][l];
    vis[l][r]=1;
    int le=dfs(l+1,r),ri=dfs(l,r-1);
    int all=sum[r]-sum[l-1];
    dp[l][r]=max(all-le,all-ri);
    return dp[l][r];
}
int main(){
    int t,n;
    cin>>t;
    while(t--){
        memset(vis,0,sizeof(vis));
        memset(dp,0,sizeof(dp));
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            sum[i]=sum[i-1]+a[i];
            vis[i][i]=1;
            dp[i][i]=a[i];
        }
        int ans=dfs(1,n);
        printf("%d\n",ans*2-sum[n]);
    }
    return 0;
}

代码2:精简版,时间较长

#include<bits/stdc++.h>
using namespace std;
int dp[1005][1005],vis[1005][1005];
int dfs(int l,int r){
    if(vis[l][r]) return dp[l][r];
    vis[l][r]=1;
    return dp[l][r]=max(dp[l][l]-dfs(l+1,r),dp[r][r]-dfs(l,r-1));
}
int main(){
    int t,n;
    cin>>t;
    while(t--){
        memset(vis,0,sizeof(vis));
        memset(dp,0,sizeof(dp));
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            vis[i][i]=1;
            scanf("%d",&dp[i][i]);
        }
        printf("%d\n",dfs(1,n));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41955236/article/details/81583094