大概作了一周,终于A了
类似于求最长公共子序列,稍有变形
当前序列 ch1 中字符为 a,序列 ch2 中字符为 b
则有 3 种配对方式:
1. a 与 b
2. a 与 -
3. - 与 b
动态转移方程:
dp[i][j] = max(dp[i - 1][j - 1] + g(ch1[i],ch2[j]) , dp[i - 1][j] + g(ch1[i],‘-') , dp[i][j-1] + g('-',ch2[j]))
代码如下:
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; int dp[205][205]; int g(char a,char b) { if( a == b ) return 5; if(a == 'A' && b == 'C' || b == 'A' && a == 'C') return -1; if(a == 'A' && b == 'G' || b == 'A' && a == 'G') return -2; if(a == 'A' && b == 'T' || b == 'A' && a == 'T') return -1; if(a == 'C' && b == 'G' || b == 'C' && a == 'G') return -3; if(a == 'C' && b == 'T' || b == 'C' && a == 'T') return -2; if(a == 'G' && b == 'T' || b == 'G' && a == 'T') return -2; if(a == 'A' && b == '-' || b == 'A' && a == '-') return -3; if(a == 'C' && b == '-' || b == 'C' && a == '-') return -4; if(a == 'G' && b == '-' || b == 'G' && a == '-') return -2; if(a == 'T' && b == '-' || b == 'T' && a == '-') return -1; } int main() { char ch1[105],ch2[105]; int t,s1,s2; scanf("%d",&t); while(t--) { memset(dp,0,sizeof(dp)); scanf("%d %s",&s1,ch1 + 1); scanf("%d %s",&s2,ch2 + 1); for(int i = 1 ; i <= s1 ; i ++) dp[i][0] = dp[i - 1][0] + g('-',ch1[i]); for(int i = 1 ; i <= s2 ; i ++) dp[0][i] = dp[0][i - 1] + g(ch2[i],'-'); for(int i = 1 ; i <= s1 ; i ++) for(int j = 1 ; j <=s2 ; j ++) dp[i][j] = max(dp[i-1][j-1] + g(ch1[i],ch2[j]), max(dp[i-1][j] + g(ch1[i],'-'),dp[i][j - 1] + g('-',ch2[j]))); printf("%d ",dp[s1][s2]); } return 0; }