目录

noip模拟66

Task 1 接力比赛

我直接用了分金币(?)的想法暴力算两个班的人能组成的所有可行能力值和及其精彩度,然后喜提TLE。实际上是个背包,用个前缀和就搞定了(注意倒序)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <bits/stdc++.h>
#define For(i, l, r) for (int i = (l), i##end = (r); i <= i##end; ++i)
#define Fordown(i, r, l) for (int i = (r), i##end = (l); i >= i##end; --i)
#define Set(a, v) memset(a, v, sizeof(a))
using namespace std;
const int maxn = 1000010;

#define int int64_t

template <typename NBXIN>
NBXIN read() {
  NBXIN s = 0, f = 1;
  char ch = getchar();
  while (ch < '0' || ch > '9') {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9') {
    s = s * 10 + ch - '0';
    ch = getchar();
  }
  return s * f;
}

struct Cls {
  int w, v;
} c1[1010], c2[1010];

int64_t v1[maxn + 5], v2[maxn + 5];
int qzn[maxn], qzm[maxn];

int32_t main() {
  freopen("game.in", "r", stdin);
  freopen("game.out", "w", stdout);
  int n, m;
  n = read<int>();
  m = read<int>();
  For(i, 1, n) {
    c1[i].w = read<int>();
    c1[i].v = read<int>();
    qzn[i] = qzn[i - 1] + c1[i].w;
  }
  For(i, 1, m) {
    c2[i].w = read<int>();
    c2[i].v = read<int>();
    qzm[i] = qzm[i - 1] + c2[i].w;
  }
  Set(v1, -0x3f);
  Set(v2, -0x3f);
  v1[0] = v2[0] = 0;
  For(i, 1, n) {
    Fordown(j, qzn[i], c1[i].w) {
      v1[j] = max(v1[j], v1[j - c1[i].w] + c1[i].v);
    }
  }
  For(i, 1, m) {
    Fordown(j, qzm[i], c2[i].w) {
      v2[j] = max(v2[j], v2[j - c2[i].w] + c2[i].v);
    }
  }
  int64_t ans = 0;
  For(i, 1, min(qzn[n], qzm[m])) ans = max(ans, v1[i] + v2[i]);
  cout << ans << endl;
  return 0;
}