题目链接:https://www.luogu.org/problemnew/show/P1140
语文很重要!!!如果题目意思都不理解,怎么可能写出正解?!两个序列都可以插空位!两个序列都可以插空位!两个序列都可以插空位!
其实如果写过最长公共子序列,这道题简直就是水题(考察阅读理解)。在这里放一波最长公共子序列,对于序列s1,s2,我们定义dp[i][j]表示考虑到s1的第i个元素,s2的第j个元素所能取到的最长公共子序列的长度,枚举i,j,若s1[i]=s2[j],则他们可以作为最长公共子序列的结尾,dp[i][j]=dp[i-1][j-1]+1;反之,s[i]和s[j]不可以作为最长公共子序列的结尾,dp[i][j]=max(dp[i][j-1],dp[i-1][j])。
本题同理,只不过字符的转换、dp数组初始化等细节需要处理好。
1 #include <cstdio> 2 #include <algorithm> 3 4 using namespace std; 5 6 const int maxn = 105; 7 const int match[5][5] = {{5, -1, -2, -1, -3}, 8 {-1, 5, -3, -2, -4}, 9 {-2, -3, 5, -2, -2}, 10 {-1, -2, -2, 5, -1}, 11 {-3, -4, -2, -1, 0}}; 12 13 int a[maxn], b[maxn], dp[maxn][maxn]; 14 char s[maxn]; 15 16 inline int toInt(char c) { 17 if (c == 'A') return 0; 18 else if (c == 'C') return 1; 19 else if (c == 'G') return 2; 20 else return 3; 21 } 22 23 int main() { 24 int al, bl; 25 scanf("%d%s", &al, s + 1); 26 for (int i = 1; i <= al; ++i) a[i] = toInt(s[i]); 27 scanf("%d%s", &bl, s + 1); 28 for (int i = 1; i <= bl; ++i) b[i] = toInt(s[i]); 29 for (int i = 1; i <= al; ++i) dp[i][0] = dp[i - 1][0] + match[a[i]][4]; 30 for (int i = 1; i <= bl; ++i) dp[0][i] = dp[0][i - 1] + match[4][b[i]]; 31 for (int i = 1; i <= al; ++i) 32 for (int j = 1; j <= bl; ++j) { 33 dp[i][j] = dp[i - 1][j - 1] + match[a[i]][b[j]]; 34 dp[i][j] = max(dp[i][j], dp[i - 1][j] + match[a[i]][4]); 35 dp[i][j] = max(dp[i][j], dp[i][j - 1] + match[4][b[j]]); 36 } 37 printf("%d", dp[al][bl]); 38 return 0; 39 }