zoukankan      html  css  js  c++  java
  • BZOJ3174. [TJOI2013]拯救小矮人(dp)

    题目链接

    https://www.lydsy.com/JudgeOnline/problem.php?id=3174

    题解

    其实此题并不需要那么多YY的部分。

    我们考虑若干个小矮人逃出的顺序。若跳出的 (k) 个小矮人依次为 (p_1, p_2, cdots , p_k),那么我们一定可以将他们排序,使得对于任意的 (i < j) 满足 (a_i + b_i < a_j + b_j) 且按照该顺序依然能保证 (k) 个小矮人全部逃出。

    证明如下:

    若对于任意 (i, j),有 (a_i + b_i < a_j + b_j),且 (j)(i) 先逃出,那么设 (i) 后面所有人的高度贡献为 (s_1)(i)(j) 之间的人的高度贡献为 (s_2)(h) 为洞深,可得:

    [a_i + a_j +b_j geq h - s_1 - s_2 ag{1} ]

    [a_i + b_i geq h - s_1 ag{2} ]

    通过 ((2)),我们可以推得:$$a_j + a_i + b_i geq h - s_1 - s_2 ag{3}$$

    通过 ((2)) 以及 (a_i + b_i < a_j + b_j),我们可以推得:$$a_j + b_j geq h - s_1 ag{4}$$

    ((3), (4)) 可以得出:(i)(j) 先逃出依然是合法的。

    这样,我们就证明了排序的正确性,那么就可以先排序再 dp 了。一个比较显然的状态是,我们设 (f_{i, j}) 表示考虑完排序后的前 (i) 个人,且已经逃走的人的 (sum a_k) 的值为 (j) 时,最多能逃走多少人。不过由于 (sum a_k) 可能很大,这样定义状态并不可行,因此我们需要把状态的第二维与状态本身的意义交换一下:设 (f_{i, j}) 表示考虑完排序后的前 (i) 个人,且已经逃走了 (j) 个人,这 (j) 个人的 (sum a_k) 的最小值。这样,我们就能在 (O(n^2)) 的时间内完成这个 dp 了。

    代码

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define X first
    #define Y second
    #define mp make_pair
    #define pb push_back
    #define debug(...) fprintf(stderr, __VA_ARGS__)
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned int uint;
    typedef pair<int, int> pii;
    typedef unsigned long long ull;
    
    template<typename T> inline void read(T& x) {
      char c = getchar();
      bool f = false;
      for (x = 0; !isdigit(c); c = getchar()) {
        if (c == '-') {
          f = true;
        }
      }
      for (; isdigit(c); c = getchar()) {
        x = x * 10 + c - '0';
      }
      if (f) {
        x = -x;
      }
    }
    
    template<typename T, typename... U> inline void read(T& x, U&... y) {
      read(x), read(y...);
    }
    
    template<typename T> inline bool checkMax(T& a, const T& b) {
      return a < b ? a = b, true : false;
    }
    
    template<typename T> inline bool checkMin(T& a, const T& b) {
      return a > b ? a = b, true : false;
    }
    
    const int N = 2e3 + 10, inf = 0x3f3f3f3f;
    
    struct State {
      int x, y;
      State () {}
      State (int x, int y): x(x), y(y) {}
      bool operator < (const State& a) const {
        return x + y < a.x + a.y;
      }
    } s[N];
    
    int n, f[N][N], h;
    
    int main() {
      read(n);
      int sa = 0;
      for (register int i = 1; i <= n; ++i) {
        read(s[i].x, s[i].y), sa += s[i].x;
      }
      sort(s + 1, s + 1 + n);
      read(h);
      memset(f, 0x3f, sizeof f);
      f[0][0] = 0;
      for (register int i = 1; i <= n; ++i) {
        for (register int j = 0; j <= i; ++j) {
          f[i][j] = f[i - 1][j];
        }
        for (register int j = 1; j <= i; ++j) {
          if (sa - f[i - 1][j - 1] + s[i].y >= h) {
            checkMin(f[i][j], f[i - 1][j - 1] + s[i].x);
          }
        }
      }
      int ans = 0;
      for (register int i = 1; i <= n; ++i) {
        if (f[n][i] < inf) {
          ans = i;
        }
      }
      printf("%d
    ", ans);
      return 0;
    }
    
  • 相关阅读:
    加载数据量大,页面卡死解决办法
    [存档]开启window7的隐藏功能虚拟wifi
    IIS发布Asp.Net网站注意事项
    [转载]总结几种C#窗体间通讯的处理方法
    调整和删除Win7休眠文件Hiberfil.sys的方法技巧,释放系统空间! ...
    [存档]Div+Css布局中经常使用的小技巧合集
    Android AndroidManifest.xml 结构详解
    Android权限详细说明
    Activity 生命周期详解
    程序员的文采
  • 原文地址:https://www.cnblogs.com/ImagineC/p/9817525.html
Copyright © 2011-2022 走看看