HDU 6199 gems gems gems

来源:互联网 发布:程序员入门先看什么书 编辑:程序博客网 时间:2024/05/21 18:37

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