洛谷 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]));
}

浙公网安备 33010602011771号