[DP]序列最大收益

181 阅读1分钟

3499. 序列最大收益 - AcWing题库

状态转移方程:

f[i][j]i个物品选定,且第i个物品前有j个物品没选f[i][j]可能是由f[iui][ju]转移而来(0uj)f[i][j]=max{f[iu1][ju]+w[aiu1][ai]}f[i][j]第 i 个物品选定,且第i个物品前有j个物品没选 \\ 则 f[i][j] 可能是由 f[i - u - i][j - u] 转移而来 (0 \leq u \leq j) \\ f[i][j] = max\{ f[i - u - 1][j - u] + w[a_{i - u - 1}][a_i] \}

完整代码:

#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 210;

int n, k, m;
int a[N], w[N][N], f[N][N];
int main() {
  scanf("%d%d%d", &n, &k, &m);

  for (int i = 1; i <= m; i++) scanf("%d", &a[i]);
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= n; j++) scanf("%d", &w[i][j]);

  for (int i = 1; i <= m; i++) {
    for (int j = 0; j <= i - 1 && j <= k; j++) {
      for (int u = j; u >= 0; u --) {
        f[i][j] = max(f[i][j], f[i - u - 1][j - u] + w[a[i - u - 1]][a[i]]);
      }
    }
  }

  int res = 0;
  for (int i = 1; i <= m; i++)
    for (int j = 1; j <= k; j++) res = max(res, f[i][j]);

  printf("%d\n", res);
  return 0;
}