[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;
}
看不见我看不见我看不见我