P9676 [ICPC2022 Jinan R] Skills Solution

P9676 [ICPC2022 Jinan R] Skills Solution

拿到题目之后我们先考虑一个朴素dp:记 \(f_{i,0/1/2,x,y}\) 表示第 \(i\) 天,我们学习第 1/2/3 个技能,同时按照序号顺延下去的另两个技能分别有 \(x,y\) 天未学习的最大经验总和。这很明显是一个 \(O(n^3)\) 的 dp,转移方程比较简单。我们考虑优化。
第一维明显可以滚动数组滚掉,于是空间复杂度来到了 \(O(n^2)\)。于是没有什么明显的优化空间了,我们考虑分析特殊性质:
如果我在某一天学习了某项技能,那么我之后一定不能让它的经验值降为 0 ,因为如果这样的话我们很明显在那一天学习其它技能是不劣甚至更优的。于是很明显有一个未学习天数的限制,不难算出这个天数是 \(2\sqrt{a_i}\),于是时间复杂度降到了 \(O(n^2)\),可以通过本题。
code

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

#define Debug printf("ZYC\n")
using Yc = long long;
using pii = pair<Yc, Yc>;

namespace Fast_Read {

inline Yc read() {
  Yc x = 0, f = 1;
  char ch = getchar();
  while (ch < '0' || ch > '9') {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
  return x * f;
}

inline void write(Yc x) {
  if (x < 0) putchar('-'), x = -x;
  if (x > 9) write(x / 10);
  putchar(x % 10 + '0');
  return;
}
}  // namespace Fast_Read

const Yc zyc = 1000 + 10;
const Yc limit = 210;

using namespace Fast_Read;
#define pc putchar
#define ps puts
#define pr printf
#define mk make_pair

Yc n, a[zyc][3], f[2][3][limit + 10][limit + 10], nxt[3];

inline void chmax(Yc &a, Yc b) { a = max(a, b); }

signed main() {
#define ZYC_
#ifdef ZYC_
  freopen(".in", "r", stdin);
  freopen(".out", "w", stdout);
#endif  // ZYC_

  Yc T = read();
  while (T--) {
    n = read();
    for (Yc i = 1; i <= n; i++)
      for (Yc j = 0; j < 3; j++) a[i][j] = read();
    memset(f, 0, sizeof(f));
    Yc cur = 0;
    for (Yc i = 0; i < n; cur ^= 1, i++) {
      for (Yc j = 0; j < 3; j++) {
        for (Yc k = 0; k < limit && k <= i; k++) {
          for (Yc l = 0; l < limit && l <= i; l++) {
            Yc nx = k ? k + 1 : 0, ny = l ? l + 1 : 0;
            if (nx < limit && ny < limit)
              chmax(f[cur ^ 1][j][nx][ny],
                    f[cur][j][k][l] - nx - ny + a[i + 1][j]);
            if (nx < limit)
              chmax(f[cur ^ 1][(j + 1) % 3][ny][1],
                    f[cur][j][k][l] - ny - 1 + a[i + 1][(j + 1) % 3]);
            if (ny < limit)
              chmax(f[cur ^ 1][(j + 2) % 3][1][nx],
                    f[cur][j][k][l] - nx - 1 + a[i + 1][(j + 2) % 3]);
          }
        }
      }
    }
    Yc ans = 0;
    for (Yc j = 0; j < 3; j++)
      for (Yc k = 0; k < limit && k <= n; k++)
        for (Yc l = 0; l < limit && l <= n; l++) chmax(ans, f[cur][j][k][l]);
    write(ans), ps("");
  }
  return 0;
}
posted @ 2024-09-27 16:18  yxans  阅读(22)  评论(0)    收藏  举报