洛谷 P4059 [Code+#1]找爸爸

update at 10.27 纠正了一点小错误。

思路

我们令 \(f_{i,j,k}\) 表示 A 串匹配了 i 个, B 串匹配了 j 个,最后一个空格的位置为 k,所产生的最大价值。

我们可以看出最后一个空格的位置可以取 4 种情况。

  • 在 A 串后边加空格
  • 在 B 串后边加空格
  • 在 A,B 串后边都加
  • 在 A,B 串后边都不加

可以发现,因为题目中给出的 a,b 都是非负数,所以如果都加上空格的话价值会减去一个非负数。这种情况下,一定是不加更优,所以我们只考虑另外的三种情况。

我们令 k=0,1,2 分别表示,都不加空格,在 A 后边加空格,在 B 后边加空格。

那么转移方程就很显然了。

  • \(f_{i,j,0} = max\{f_{i-1,j-1,0},f_{i-1,j-1,1},f_{i-1,j-1,2} \} + d_{x_i,y_j}\)
  • \(f_{i,j,1} = max\{f_{i,j-1,1} - b,f_{i,j-1,0}-a,f_{i,j-1,2} - a\}\)
  • \(f_{i,j,2} = max\{f_{i-1,j,2} - b,f_{i-1,j,0}-a,f_{i-1,j,1} - a\}\)

\(f_{i,j,0}\) 是两边都不加空格,显然是从上次的三个中取最大值,然后加上现在这个位置的价值。

\(f_{i,j.1}\) 是在 A 后加空格,他 \(f_{i.j-1,1}\) 的时候可以根据转移方程看出是在 A 串上放的空格,所以我们 -b。在 \(f_{i,j-1,0}\) 的时候两个都没有放,所以减去 a ,\(f_{i,j-1,2}\) 的时候是在 B 上放的空格,所以我们减去 a 就行了。

\(f_{i,j,2}\) 的时候与上述类似,不再赘述。

code

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define int long long
#define N 100010
#define M 3010

using namespace std;
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;
char s1[M], s2[M];
int n, m, a, b, x[M], y[M], d[M][M], f[M][M][3];

int read() {
  int s = 0, f = 0; char ch = getchar();
  while (!isdigit(ch)) f |= (ch == '-'), ch = getchar();
  while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
  return f ? -s : s;
}
int pd(char s) {
  if (s == 'A') return 1;
  else if (s == 'T') return 2;
  else if (s == 'G') return 3;
  else return 4;
}
signed main() {
  cin >> s1 >> s2;
  for (int i = 1; i <= 4; i++)
    for (int j = 1; j <= 4; j++)
      d[i][j] = read();
  a = read(), b = read();
  n = strlen(s1), m = strlen(s2);
  for (int i = 1; i <= n; i++) x[i] = pd(s1[i - 1]);
  for (int i = 1; i <= m; i++) y[i] = pd(s2[i - 1]);
  for (int i = max(n, m); i; --i) {
    f[0][i][0] = f[i][0][0] = f[0][i][2] = f[i][0][1] = -(1LL << 60);
    f[0][i][1] = f[i][0][2] = - a - b * (i - 1);
  }
  f[0][0][1] = f[0][0][2] = -(1LL << 60);
  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[x[i]][y[j]];
      f[i][j][1] = max(f[i][j - 1][1] - b, max(f[i][j - 1][0] - a, f[i][j - 1][2] - a));
      f[i][j][2] = max(f[i - 1][j][2] - b, max(f[i - 1][j][0] - a, f[i - 1][j][1] - a));
    }
  cout << max(f[n][m][0], max(f[n][m][1], f[n][m][2]));
}
posted @ 2020-10-26 08:03  Kersen  阅读(136)  评论(0)    收藏  举报