HDU 6199 gems gems gems

Source: 2017 ACM/ICPC Asia Regional Shenyang Online

Problem: 给你n个不同价值的宝石,排成一排,两个人轮流拿,若前者拿了k个,后者只能拿k或k+1个,第一个人最开始只能拿1个或2个,他要使两人之差最大,第二个人要使两人之差最小,两个人都是最优的拿法,问其结果。

Idea: DP。 由于k最大取值约为 sqrt(n2.0) ,所以可以将 O(nn2) 的复杂度优化到 O(nsqrt(n2)2) ,空间优化用到了取模的技巧。

Code:

#include<bits/stdc++.h>
using namespace std;

#define fi first
#define se second
#define pb push_back
#define CLR(A, X) memset(A, X, sizeof(A))
#define bitcount(X) __builtin_popcountll(X)
typedef long long LL;
typedef pair<int, int> PII;
const double eps = 1e-10;
const int MOD = 255;
const auto INF = 0x3f3f3f3f;
int dcmp(double x) { if(fabs(x) < eps) return 0; return x<0?-1:1; }

const int MAXN = 2e4+5;

int sum[MAXN], dp[2][256][256];

int main() {
    int X, n;
    scanf("%d", &X);
    while(X--) {
        CLR(dp, 0);
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) {
            scanf("%d", &sum[i]);
            sum[i] += sum[i-1];
        }
        int k = sqrt(n*2.0)+1;
        for(int i = n; i >= 1; i--) {
            for(int j = 1; j<=k && i+j-1<=n; j++) {
                int u = i&MOD, v = (i+j)&MOD, d = sum[i+j-1]-sum[i-1];
                int &d0 = dp[0][u][j], &d1 = dp[1][u][j];
                d0 = dp[1][v][j]+d;
                d1 = dp[0][v][j]-d;
                if(i+j <= n) {
                    v = (v+1)&MOD, d += sum[i+j]-sum[i+j-1];
                    d0 = max(d0, dp[1][v][j+1]+d);
                    d1 = min(d1, dp[0][v][j+1]-d);
                }
            }
        }
        printf("%d\n", dp[0][1][1]);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值