洛谷题单指南-动态规划3-P1140 相似基因
原题链接:https://www.luogu.com.cn/problem/P1140
题意解读:两个只包含A、C、G、T4个字符的序列,根据已经定义好的字符-字符的相似度,计算两个序列最大的相似度,两个序列必须每个字符都配对,如果字符不够,可以插入'-'代替。
解题思路:
本题要解决几个问题:
1、状态表示
既然有两个序列,设分别为a[n]、b[m],很容易想到设dp[i][j]表示a序列1~i和b序列1~j的相似度
为了方便查表计算字符-字符对应的相似度,可以将'A'、'C'、'G'、'T'、'-'转换为0,1,2,3,4
这样可以用二维数组保存所有的相似度关系:
int s[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
};
2、状态转移
对与a[1~i]和b[1~j],重点考虑最后一个字符的配对关系,有三种可能:
a[i]和b[j]配对:dp[i][j] = dp[i-1][j-1] + s[a[i]][b[j]]
在a[i]后面插入'-',用'-'和b[i]配对:dp[i][j] = dp[i][j-1] + s[4][b[j]]
在b[i]后面插入'-',用a[i]和'-'配对:dp[i][j] = dp[i-1][j] + s[a[i]][4]
以上三种情况取max即可
3、初始化
由于i,j都从1开始枚举,而递推式中会依赖于i-1,j-1,因此要对dp[i][0]以及dp[0][i]进行初始化
dp[i][0]表示a[1~i]与空串的相似度,就是a中每个字符与'-'配对的相似度之和
dp[0][i]表示空串与b[1~i]的相似度,就是'-'与b中每个字符配对的相似度之和
dp[0][0]保持0即可,没有配对发生
4、结果
dp[n][m]
100分代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 105;
int n, m;
int a[N], b[N]; //对应两组碱基序列, A,C,G,T分别对应0,1,2,3,-对应4
int dp[N][N]; //dp[i][j]表示a序列1~i和b序列1~j的相似度
int s[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 getnum(char x)
{
if(x == 'A') return 0;
if(x == 'C') return 1;
if(x == 'G') return 2;
if(x == 'T') return 3;
if(x == '-') return 4;
}
int main()
{
char x;
cin >> n;
for(int i = 1; i <= n; i++)
{
cin >> x;
a[i] = getnum(x);
}
cin >> m;
for(int i = 1; i <= m; i++)
{
cin >> x;
b[i] = getnum(x);
}
for(int i = 1; i <= n; i++)
{
dp[i][0] = dp[i-1][0] + s[a[i]][4]; //初始化所有的dp[i][0]为a:1~i对应'-'的相似度之和
}
for(int i = 1; i <= m; i++)
{
dp[0][i] = dp[0][i-1] + s[4][b[i]]; //初始化所有的dp[0][i]为'-'对应b:1~i的相似度之和
}
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= m; j++)
{
dp[i][j] = max(dp[i-1][j-1] + s[a[i]][b[j]], max(dp[i][j-1] + s[4][b[j]], dp[i-1][j] + s[a[i]][4]));
}
}
cout << dp[n][m];
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?