[Code+#1] 找爸爸

[Code+#1] 找爸爸

一道简单的 \(DP\) .

基本算是一眼秒了吧?

首先我们要考虑的就是这个空格怎么放, 看一下数据范围, 我们发现两行一定不会同时出现空格, 因为 \(A, B\) 都是正整数, 所以我们只需要考虑三种情况, 两行都不是空格, 第一行是空格, 第二行是空格, 这就够了.

于是状态就自然而然的设出来了: \(f[i][j][0/1/2]\) 表示第一行到 \(i\) , 第二行到 \(j\) , 两行结尾都不是空格/第一行结尾是空格/第二行结尾是空格的最大相似度.

转移也很简单.

  • \(f[i][j][0]\) 表示当前两行分别加入了一位, 所以 \(f[i][j][0] = \max(f[i - 1][j - 1][0/1/2]) + d[a[i]][b[j]]\) .
  • \(f[i][j][1]\) 表示第一行放了个空格, 所以 \(f[i][j][1] = \max(f[i][j - 1][1] - B, \max(f[i][j - 1][0], f[i][j - 1][2]) - A)\) .
  • \(f[i][j][2]\) 表示第二行放了个空格, 所以 \(f[i][j][2] = \max(f[i - 1][j][2] - A, \max(f[i - 1][j][0], f[i - 1][j][1]) - A)\) .

于是就快乐的写完了, 但是要注意预处理, 记得处理 \(f[0][i][1]\)\(f[i][0][2]\) .

这道题很久之前就做来着, 但是当时以为是贪心, 因为 \(B < A\) 嘛, 就使劲贪心, 到最后也没贪出来, 现在一看, 这不一道简单的 \(DP\) 嘛, 看来我还是有点长进的.

\(code:\)

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

int read() {
  int x = 0, f = 1;
  char ch = getchar();
  for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
  for (; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);
  return x * f;
}

void print(int x) {
  if (x < 0) putchar('-'), x = -x;
  static short top = 0, stk[35];
  do {
    stk[top++] = x % 10;
    x /= 10;
  } while (x);
  while (top) putchar(stk[--top] + 48);
}

const int N = 3005;

int n, m, A, B, len, a[N], b[N], f[N][N][3], d[5][5];
char s[N], t[N];

int Get(char x) {
  if (x == 'A') return 1;
  else if (x == 'T') return 2;
  else if (x == 'G') return 3;
  else return 4;
}

int main() {
  scanf("%s%s", s + 1, t + 1);
  n = strlen(s + 1), m = strlen(t + 1), len = n + m;
  for (int i = 1; i <= n; i++) a[i] = Get(s[i]);
  for (int i = 1; i <= m; i++) b[i] = Get(t[i]);
  for (int i = 1; i <= 4; i++) {
    for (int j = 1; j <= 4; j++) {
      d[i][j] = read();
    }
  }
  A = read(), B = read();
  memset(f, -0x3f, sizeof(f));
  f[0][0][0] = 0, f[1][0][2] = f[0][1][1] = -A;
  for (int i = 2; i <= n; i++) f[i][0][2] = f[i - 1][0][2] - B;
  for (int i = 2; i <= m; i++) f[0][i][1] = f[0][i - 1][1] - B;
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= m; j++) {
      f[i][j][0] = max(f[i - 1][j - 1][0], max(f[i - 1][j - 1][1], f[i - 1][j - 1][2])) + d[a[i]][b[j]];
      f[i][j][1] = max(f[i][j - 1][1] - B, max(f[i][j - 1][0], f[i][j - 1][2]) - A);
      f[i][j][2] = max(f[i - 1][j][2] - B, max(f[i - 1][j][0], f[i - 1][j][1]) - A);
    }
  }
  print(max(f[n][m][0], max(f[n][m][1], f[n][m][2])));
  return 0;
}
posted @ 2021-09-28 09:14  sshadows  阅读(36)  评论(0编辑  收藏  举报