zoukankan      html  css  js  c++  java
  • bzoj 2091 The Minima Game

    题目传送门

      需要验证权限的传送门

    题目大意

      Alice和Bob轮流取$n$个正整数,Alice先进行操作。每次每人可以取任意多的数,得分是这一次取的所有数中的最小值。Alice和Bob都足够聪明,他们的策略都是让自己的得分减去对方的得分尽量大。问最终Alice的得分减去Bob的得分。

      因为与顺序无关,所以考虑贪一下心。

      因为使得分劲量大,所以肯定先把大的数取走。

      又因为一次取的得分是所有取的数中的最小值,所以取走的数是排序后的连续的一段。否则对方可以取你间断的那一个数,这样显然不优。

      所以用$f[i]$表示取走前$i$大后,Alice的得分减去Bob的得分,但是这样无法确定转移时谁在操作。

      因此把这个游戏过程倒过来dp,用$f[i]$表示在前$i$小中进行游戏,先手减去后手的得分。

      转移枚举剩下的局面就行了。

      然后这样转移$O(n^{2})$。但是发现dp式子蜜汁雷同:$f[i] = max_{j = 1}^{i - 1} {f[j] + a_{j + 1}}$

      直接记一个东西就可以$O(1)$转移了。

      时间复杂度$O(nlog n)$

    Code

     1 /**
     2  * bzoj
     3  * Problem#2091
     4  * Accepted
     5  * Time: 1440ms
     6  * Memory: 13016k
     7  */
     8 #include <bits/stdc++.h>
     9 #ifndef WIN32
    10 #define Auto "%lld"
    11 #else
    12 #define Auto "%I64d"
    13 #endif
    14 using namespace std;
    15 
    16 #define ll long long
    17 
    18 int n;
    19 ll *f;
    20 int *ar;
    21 
    22 inline void init() {
    23     scanf("%d", &n);
    24     f = new ll[(n + 1)]; 
    25     ar = new int[(n + 1)];
    26     for (int i = 1; i <= n; i++)
    27         scanf("%d", ar + i);
    28 } 
    29 
    30 inline void solve() {
    31     sort(ar + 1, ar + n + 1); 
    32     f[1] = ar[1];
    33     for (int i = 2; i <= n; i++)
    34         f[i] = max(f[i - 1], ar[i] - f[i - 1]);
    35     printf(Auto"
    ", f[n]);
    36 }
    37 
    38 int main() {
    39     init();
    40     solve();
    41     return 0;
    42 }
  • 相关阅读:
    Linq增删查改
    ObjectiveC 的一些记录
    MAX+VC版的RenderMonkey
    PHP校验身份证是否合法
    将小程序scene中的字符串转为对象
    使用JavaScript与Servlet实现客户端与服务器端验证
    分析jdbc程序的编写步骤和原理
    解析Tomcat生成源代码分析javaBean与对象的生成关系
    《Python基础教程》要点(十):充电时刻:导入模块
    《Python基础教程》要点(七):更加抽象:类
  • 原文地址:https://www.cnblogs.com/yyf0309/p/8535734.html
Copyright © 2011-2022 走看看