•参考资料
[1]:https://www.cnblogs.com/real-l/p/9712029.html
[2]:https://www.luogu.org/problemnew/solution/P1140
•题解
方法一:枚举所有可能(记忆型DP)
相关变量解释:
m,n...................................................分别代表串1、串2的长度
a[maxn]............................................a[i] : 串 1 的 i 位置的字母对应的数字(下标从 1 开始,并且 A->1;C->2;G->3;T->4)
b[maxn]............................................b[i] : 串 2 的 i 位置的字母对应的数字(解释同上)
dp[maxn][maxn]................................dp[ i ][ j ] : 串 1 的 1~i 与 串 2 的 1~j 匹配所获得的最大相似度;
table[maxn][maxn]............................对应题干中的基因配对表
步骤:
(1):预处理出dp[ i ][0] , dp[0][ j ](1 ≤ i ≤ m , 1 ≤ j ≤ n)
1 for(int i=1;i <= m;++i) 2 dp[i][0]=dp[i-1][0]+table[a[i]][5]; 3 4 for(int i=1;i <= n;++i) 5 dp[0][i]=dp[0][i-1]+table[b[i]][5];这一操作是什么意思呢?
根据dp[][]的含义可知,dp[ i ][0]表示的是串 1 匹配到 i 字符,串2匹配到0 的最大相似度;
串2匹配到 0 字符意味着串1的第 i 个字符匹配' - '吗,对应着table表中的table[a[ i ]][5];
而前 i-1 个字符匹配的也是' - ',根据最大相似度的定义,所以匹配到 i 字符处的最大相似度就是
table[a[0]][5]+table[a[1]][5]+........+table[a[ i ]][5],此处用前缀和表示;
同理可得dp[ 0 ][ i ]得含义。
(2):状态转移方程
对于串1的 i 位置,串2的 j 位置时,有一下三种可能:
①:串1的 i 位置和 ' - ' 配对 dp[ i-1 ][ j ]+table[ a[i] ][5];
②:串2的 j 位置和 ' - ' 配对 dp[ i ][ j-1 ]+table[ b[j] ][5];
③:串1的 i 位置和串2的 j 位置配对 dp[ i-1 ][ j-1 ]+table[ a[i] ][ b[j] ];
从中找出最大的相似度赋值给dp[ i ][ j ];
•Code
View Code1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 const int maxn=100+50; 5 6 int m,n; 7 int dp[maxn][maxn]; 8 int a[maxn],b[maxn]; 9 int table[5][6]={ 10 {0}, 11 {0,5,-1,-2,-1,-3}, 12 {0,-1,5,-3,-2,-4}, 13 {0,-2,-3,5,-2,-2}, 14 {0,-1,-2,-2,5,-1} 15 }; 16 void Solve() 17 { 18 for(int i=1;i <= m;++i) 19 dp[i][0]=dp[i-1][0]+table[a[i]][5]; 20 for(int i=1;i <= n;++i) 21 dp[0][i]=dp[0][i-1]+table[b[i]][5]; 22 for(int i=1;i <= m;++i) 23 { 24 for(int j=1;j <= n;++j) 25 { 26 dp[i][j]=dp[i-1][j]+table[a[i]][5];// 串1的 i 字符匹配 ' _ ' 27 dp[i][j]=max(max(dp[i][j],dp[i][j-1]+table[b[j]][5]),dp[i-1][j-1]+table[a[i]][b[j]]);//串2的j字符匹配'_' 和 串1的i字符匹配串2的j字符 28 } 29 } 30 printf("%d\n",dp[m][n]); 31 } 32 int main() 33 { 34 scanf("%d",&m); 35 getchar(); 36 for(int i=1;i <= m;++i) 37 { 38 char letter=getchar(); 39 if(letter == 'A') 40 a[i]=1; 41 else if(letter == 'C') 42 a[i]=2; 43 else if(letter == 'G') 44 a[i]=3; 45 else 46 a[i]=4; 47 } 48 scanf("%d",&n); 49 getchar(); 50 for(int i=1;i <= n;++i) 51 { 52 char letter=getchar(); 53 if(letter == 'A') 54 b[i]=1; 55 else if(letter == 'C') 56 b[i]=2; 57 else if(letter == 'G') 58 b[i]=3; 59 else 60 b[i]=4; 61 } 62 Solve(); 63 }