版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/smmyy022/article/details/81940195
题解
这题和那道经典的最长相同子序列很类似,是一道简单的(?)线性dp。
仔细思考一下什么是状态,选择以及相互之间的影响。
F [ i ] [ j ] : 代表 i,j 位置为止的两段串的最大分数
转移方程 // 显然就3种选择 i,j配对 i不配对 以及 j不配对
F [ i+1 ] [ j+1 ] = max{
F [ i ] [ j ] + points[ a[i] ] [ b[j] ] ,
F [ i+1 ] [ j ] + points[4] [ b[j] ] ,
F [ i ] [ j+1 ] + points[ a[i] ] [4]
}
Code
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <map>
#include <algorithm>
using namespace std;
int n,m;
int a[102],b[102];
int f[102][102];
int points[5][5] = { {5,-1,-2,-1,-3},
{-1,5,-3,-2,-4},
{-2,-3,5,-2,-2},
{-1,-2,-2,5,-1},
{-3,-4,-2,-1,0} };
int main(){
map<char,int> mm;
mm['A'] = 0;
mm['C'] = 1;
mm['G'] = 2;
mm['T'] = 3;
cin>>n;
char c;
for(int i=1;i<=n;i++){
cin>>c;
a[i] = mm[c] ;
}
cin>>m;
for(int i=1;i<=m;i++){
cin>>c;
b[i] = mm[c];
}
// 0位置预处理
for(int i=1;i<=n;i++) f[i][0] = f[i-1][0]+points[ a[i] ][4];
for(int i=1;i<=m;i++) f[0][i] = f[0][i-1]+points[ b[i] ][4];
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
f[i][j] = -100;// 负值初始化 为求max
f[i][j] = max(f[i][j], f[i-1][j]+points[4][ a[i] ] );
f[i][j] = max(f[i][j], f[i][j-1]+points[ b[j] ][4] );
f[i][j] = max(f[i][j], f[i-1][j-1]+points[a[i]][b[j]] );
}
}
cout<<f[n][m]<<endl;
return 0;
}