对部分题解的疑惑?
查看原帖
对部分题解的疑惑?
36078
uhgariej楼主2023/2/23 22:33

我看到一篇题解是这样定义状态的: 令f[i][j][k][first]为在第i个位置,本位置选了第j种树,前一个位置选第k种树,第一棵树种的是first时的最大观赏值

那么在第n棵树的时候, 状态dp[n][j][k][first], 只能知道第n - 1棵树, 第n棵树, 第一棵树分别种了第k, j, first类别的树,此时可以判断第n棵树的状态是否符合都比相邻的高或低的要求. 但是却不能判断第一棵树的状态是否也符合要求, 因为第一棵树的状态判断需要知道第二棵树种了什么.

所以不知道是数据过弱,还是我想的有问题?

下面是我考虑第一棵树以及第二棵树分别种了什么类别的树的AC代码.

ps. 记录首的状态是什么, 通常是解决环的一个好办法, 因为首尾相连, 当我们考虑到的时候, 如果还知道的状态, 会简单处理很多.

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

static const int N = 1e5 + 5;
const int INF = 1e9;
// dp[i][j][k][first][second]表示考虑前i棵树, 第i棵树种第j类树, 第i - 1棵树种第k类树
// 且第一棵树和第二棵树分别种第first, second类树, 能获得的最大值.
// 时间复杂度: 状态数 * 转移数 = O(n * 3 * 3 * 3 * 3) * O(3) = O(n * (3 ^ 5))
int n, a[N][4], dp[N][4][4][4][4];

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  
  cin >> n;
  for (int i = 1; i <= n; ++i) {
    cin >> a[i][1] >> a[i][2] >> a[i][3];
  }
  int ans = 0;
  for (int first = 1; first <= 3; ++first) {
    for (int second = 1; second <= 3; ++second) {
      for (int i = 2; i <= n; ++i) {
        for (int j = 1; j <= 3; ++j) {
          for (int k = 1; k <= 3; ++k) {
            // dp[i][j][k][first][second];
            int &ret = dp[i][j][k][first][second];
            if (i == 2) {
              if (j == second && k == first) ret = a[i][j] + a[i - 1][k];
              else ret = -INF;
            } else {
              // 第i棵树种第j类树, 第i - 1棵树种第k类树, 枚举第i - 2棵树种那类树.
              // u, k, j
              for (int u = 1; u <= 3; ++u) {
                if (u < k && k > j) {
                  ret = std::max(ret, dp[i - 1][k][u][first][second] + a[i][j]);
                }
                if (u > k && k < j) {
                  ret = std::max(ret, dp[i - 1][k][u][first][second] + a[i][j]);
                }
              }
            }
            // 检查第n棵树以及第1棵树是否符合要求.
            if (i == n) {
              if ((first < j && j > k) && (first < j && first < second)) ans = std::max(ans, ret);
              if ((first > j && j < k) && (first > j && first > second)) ans = std::max(ans, ret);
            }
          }
        }
      }
      
    }
  }
  cout << ans;
  return 0;
}

2023/2/23 22:33
加载中...