洛谷OJ: P1140 相似基因(DP)

1.令第一条链的碱基与空碱基配对

2.令第二条链的碱基与空碱基配对

3.令两条链的碱基相互配对

dp[i][j] = max{dp[i][j], dp[i-1][j]+a[i]与空碱基的匹配值, dp[i][j-1]+b[j]与空碱基的匹配值, dp[i-1][j-1]+a[i]与b[i]的匹配值}

/**
*	题目: 洛谷OJ:  P1140 相似基因(DP)
*	题型: DP
**/
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

const int maxn = 100+10;
const int w[6][6] = {{0,0,0,0,0,0},
{0,5,-1,-2,-1,-3},
{0,-1,5,-3,-2,-4},
{0,-2,-3,5,-2,-2},
{0,-1,-2,-2,5,-1},
{0,-3,-4,-2,-1,0}};
int dp[maxn][maxn], a[maxn], b[maxn], n, m;

int create() {
char ch;
cin >> ch;
switch(ch) {
case 'A': return 1;
case 'C': return 2;
case 'G': return 3;
case 'T': return 4;
}
}

int main()  {
/************input**************/
cin >> n; for(int i = 1; i <= n; i++) a[i] = create();
cin >> m; for(int i = 1; i <= m; i++) b[i] = create();
/*******************************/

/************init***************/
//初始化工作一定要做好, 开始因为初始化疏忽大意WA了一个点
memset(dp, -0x3f, sizeof(dp));
dp[0][0] = 0;
for(int i = 1; i <= n; i++) dp[i][0] = dp[i-1][0] + w[a[i]][5];
for(int i = 1; i <= m; i++) dp[0][i] = dp[0][i-1] + w[b[i]][5];
/*******************************/
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
//为了方便阅读就不使用这种写法了
//dp[i][j] = max( dp[i][j], max( dp[i-1][j]+w[a[i]][5], max(dp[i][j-1]+w[b[j]][5], dp[i-1][j-1]+w[a[i]][b[j]]) ) );
dp[i][j] = max(dp[i][j], dp[i-1][j]+w[a[i]][5]); //令a[i]与空碱基配对
dp[i][j] = max(dp[i][j], dp[i][j-1]+w[b[j]][5]); //令b[j]与空碱基配对
dp[i][j] = max(dp[i][j], dp[i-1][j-1]+w[a[i]][b[j]]); //令a[i]与b[j]配对
}
}
cout << dp[n][m] << endl;
return 0;
}