P4059题解
传送门:https://www.luogu.com.cn/problem/P4059
去掉连续段贡献即是经典的编辑字符问题,用 dp 解决。考虑在状态上加上是否在当前位置后加了空格,由于两个序列在相同位置有空格显然不优,因为剔除后结果仍然没有发生改变,因此只需要三种状态,也意味着只需要 dp 两个序列尾部即可。
令 \(dp_{i,j,0/1/2}\) 分别表示计算到 \(A\) 的 \(i\) 位,\(B\) 的 \(j\) 位,且 \(A\),\(B\) 末尾均没有空格/\(A\) 末尾有空格,\(B\) 末尾没有空格/\(A\) 末尾没有空格,\(B\) 末尾有空格。转移方程见代码:
#include <bits/stdc++.h>
const int N = 5e5 + 1;
using namespace std;
int mp[128], val[5][5], dp[3001][3001][3];
char s1[3001], s2[3001];
int main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> s1 + 1 >> s2 + 1;
int l1 = strlen(s1 + 1), l2 = strlen(s2 + 1);
memset(dp, -0x3f, sizeof dp);
for (int i = 1; i <= 4; ++i) for (int j = 1; j <= 4; ++j) cin >> val[i][j];
mp['A'] = 1, mp['T'] = 2, mp['G'] = 3, mp['C'] = 4;
int A, B;
cin >> A >> B;
dp[0][0][0] = 0;
for (int i = 0; i <= l1; ++i) {
for (int j = 0; j <= l2; ++j) {
if (i && j)
dp[i][j][0] = max(dp[i - 1][j - 1][0],
max(dp[i - 1][j - 1][1], dp[i - 1][j - 1][2])) + val[mp[s1[i]]][mp[s2[j]]];
if (j) dp[i][j][1] = max(max(dp[i][j - 1][0], dp[i][j - 1][2]) - A, dp[i][j - 1][1] - B);
if (i) dp[i][j][2] = max(max(dp[i - 1][j][0], dp[i - 1][j][1]) - A, dp[i - 1][j][2] - B);
}
}
cout << max(max(dp[l1][l2][0], dp[l1][l2][1]), dp[l1][l2][2]);
return 0;
}

浙公网安备 33010602011771号