HDU - 6199 gems gems gems (DP)

有n(2e4)个宝石
两个人轮流从左侧取宝石,Alice先手,首轮取1个或2个宝石,
如果上一轮取了k个宝石,则这一轮只能取k或k+1个宝石。
一旦不能再取宝石就结束。
双方都希望自己拿到的宝石数比对方尽可能多。
问你,先手比后手多拿的最大宝石数。

 

 

 

 

 

dp[s][k] 表示从已经拿了s个,这一次可以拿k个,也可以拿k+1个。

那么dp[s][k] 表示 已经拿了s个,这一次可以拿k个或k+1个的最大差值。

 

 

 

#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn = 20000 + 10;
const int INF = 0x3f3f3f3f;

int a[maxn], sum[maxn];
int dp[maxn][212];
int n;

int DP(int s, int k) 
{
    if(dp[s][k] != -INF) return dp[s][k];
    if (s+k <= n) dp[s][k] = max(dp[s][k], sum[s+k]-sum[s]-DP(s+k, k));
    if (s+k+1 <= n) dp[s][k] = max(dp[s][k], sum[s+k+1]-sum[s]-DP(s+k+1, k+1));
    if (dp[s][k] == -INF) dp[s][k] = 0;
    return dp[s][k];
}

void init()
{
    memset(sum, 0, sizeof(sum));
    for (int i = 0; i < maxn; i++)
        for (int j = 0; j <= 200; j++)
            dp[i][j] = -INF;
}

int main()
{
    int t;
    scanf("%d", &t);
    for (int ca = 1; ca <= t; ca++)
    {
        init();
        scanf("%d", &n);
        for (int i = 1; i <= n; i++)
            scanf("%d", &a[i]), sum[i] = sum[i-1] + a[i];
        printf("%d\n", DP(0, 1));
    }
}

 

posted @ 2018-08-30 11:26  jvruodejrLS  阅读(312)  评论(0编辑  收藏  举报

Contact with me