洛谷 P1140 相似基因(DP)
•参考资料
[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)
for(int i=;i <= m;++i)
dp[i][]=dp[i-][]+table[a[i]][]; for(int i=;i <= n;++i)
dp[][i]=dp[][i-]+table[b[i]][];这一操作是什么意思呢?
根据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
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=+; int m,n;
int dp[maxn][maxn];
int a[maxn],b[maxn];
int table[][]={
{},
{,,-,-,-,-},
{,-,,-,-,-},
{,-,-,,-,-},
{,-,-,-,,-}
};
void Solve()
{
for(int i=;i <= m;++i)
dp[i][]=dp[i-][]+table[a[i]][];
for(int i=;i <= n;++i)
dp[][i]=dp[][i-]+table[b[i]][];
for(int i=;i <= m;++i)
{
for(int j=;j <= n;++j)
{
dp[i][j]=dp[i-][j]+table[a[i]][];// 串1的 i 字符匹配 ' _ '
dp[i][j]=max(max(dp[i][j],dp[i][j-]+table[b[j]][]),dp[i-][j-]+table[a[i]][b[j]]);//串2的j字符匹配'_' 和 串1的i字符匹配串2的j字符
}
}
printf("%d\n",dp[m][n]);
}
int main()
{
scanf("%d",&m);
getchar();
for(int i=;i <= m;++i)
{
char letter=getchar();
if(letter == 'A')
a[i]=;
else if(letter == 'C')
a[i]=;
else if(letter == 'G')
a[i]=;
else
a[i]=;
}
scanf("%d",&n);
getchar();
for(int i=;i <= n;++i)
{
char letter=getchar();
if(letter == 'A')
b[i]=;
else if(letter == 'C')
b[i]=;
else if(letter == 'G')
b[i]=;
else
b[i]=;
}
Solve();
}
•初始疑惑
状态转移方程对应的三种状态没有表示处串 1 的 i 字符匹配 ' - '和串2的 j 字符匹配 ' - ' 这一情况啊。
•我的理解
对于情况① dp[ i-1 ][ j ]+table[ a[i] ][5]:
dp[ i-1 ][ j ]的意思是, i 之前的字符和串 2 匹配过程中所能获得的最大的相似度,
如果串1的 i 字符匹配 ' - '和串2的 j 字符匹配 ' - ' 这一情况对应的相似度最大,那么 dp[ i-1 ][ j ]就是串2的 j 字符匹配 ' - '。
情况②同理。
•分析:此题为什么可以用DP来做?
1.满足最优子结构性质
当串1来到 i 位置,串2来到 j 位置,如果dp[ i ][ j ]对应的解是最优解,则其之前的位置dp[1.....i-1][1........j-1]也一定是最优解。
2.无后效性性质
当前状态值dp[ i ][ j ]一旦确定,则此后过程的匹配就只和dp[ i ][ j ]这个状态的值有关,和之前是采取哪种匹配方式演变到当前的状态没有关系。
分割线:2019.6.11
•简短题解
最近在练习动规,拿出之前做的题重新做一下;
定义dp[ i ][ j ]表示串 s 的 1~i 与串 t 的 1~j 的最大匹配度;
dp[ i ][ j ]=max{ dp[ i-1 ][ j-1 ]+|si -- tj| , dp[ i-1 ][ j ]+|si -- ' - '| , dp[ i ][ j-1 ]+|tj -- ' - '| | 1 ≤ j ≤ |t| };
•Code
#include<bits/stdc++.h>
using namespace std;
#define MAX(a,b,c) max(max(a,b),c)
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn=+; int n,m;
char s[maxn];
char t[maxn];
map<char ,int >f;
int g[][]=
{
{,-,-,-,-},
{-,,-,-,-},
{-,-,,-,-},
{-,-,-,,-},
{-,-,-,-}
}; int dp[maxn][maxn];
int Solve()
{
f['A']=,f['C']=,f['G']=,f['T']=; mem(dp,);
dp[][]=g[f[s[]]][];
for(int i=;i <= n;++i)
dp[i][]=dp[i-][]+g[f[s[i]]][]; dp[][]=g[f[t[]]][];
for(int j=;j <= m;++j)
dp[][j]=dp[][j-]+g[f[t[j]]][]; for(int i=;i <= n;++i)
{
for(int j=;j <= m;++j)
{
int x=f[s[i]];
int y=f[t[j]];
dp[i][j]=dp[i-][j-]+g[x][y];
dp[i][j]=MAX(dp[i][j],dp[i-][j]+g[x][],dp[i][j-]+g[y][]);
}
}
return dp[n][m];
}
int main()
{
// freopen("C:\\Users\\hyacinthLJP\\Desktop\\in&&out\\contest","r",stdin);
scanf("%d%s",&n,s+);
scanf("%d%s",&m,t+);
printf("%d\n",Solve()); return ;
}
洛谷 P1140 相似基因(DP)的更多相关文章
- 洛谷P1140 相似基因 (DP)
洛谷P1140 相似基因 题目背景 大家都知道,基因可以看作一个碱基对序列.它包含了44种核苷酸,简记作A,C,G,TA,C,G,T.生物学家正致力于寻找人类基因的功能,以利用于诊断疾病和发明药物. ...
- 洛谷P1140 相似基因【线性dp】
题目:https://www.luogu.org/problemnew/show/P1140 题意: 给定两串基因串(只包含ATCG),在其中插入任意个‘-’使得他们匹配.(所以一共是5种字符) 这5 ...
- 洛谷P1140 相似基因(线性DP)
题目背景 大家都知道,基因可以看作一个碱基对序列.它包含了444种核苷酸,简记作A,C,G,TA,C,G,TA,C,G,T.生物学家正致力于寻找人类基因的功能,以利用于诊断疾病和发明药物. 在一个人类 ...
- 洛谷 P1140 相似基因 ( 线性DP || 类LCS )
题意 : 题目链接 分析 : 可以观察到给出的配对代价表中对角线部分是正数 其余的都是负数,也就是说让相同字母的匹配的越多越好 即找出 LCS 但是这里 DP 的过程需要记录一下代价 有关 LCS ...
- 洛谷P1140 相似基因
题目:https://www.luogu.org/problemnew/show/P1140 分析: 本题一看就知道是一道动归,其实和字串距离非常的像,只不过多了题目规定的匹配相似度罢了. 匹配的相似 ...
- 洛谷 P1140 相似基因 题解
每日一题 day23 打卡 Analysis dp[i][j]表示序列A中前i个与序列B中前j个匹配的相似度最大值 所以,dp方程很容易想到: 1.让a[i]与b[j]匹配 2.让a[i]与B序列中一 ...
- 【洛谷P1140 相似基因】动态规划
分析 f[i][j] 表示 1数组的第i位和2数组的第j位匹配的最大值 f[1][1]=-2 f[2][1]=-2+5=3 f[3][1]=-2+5+5=8 三个决策: 1.由f[i-1][j-1]直 ...
- 洛谷P1108 低价购买[DP | LIS方案数]
题目描述 “低价购买”这条建议是在奶牛股票市场取得成功的一半规则.要想被认为是伟大的投资者,你必须遵循以下的问题建议:“低价购买:再低价购买”.每次你购买一支股票,你必须用低于你上次购买它的价格购买它 ...
- NOIP2017提高组Day2T2 宝藏 洛谷P3959 状压dp
原文链接https://www.cnblogs.com/zhouzhendong/p/9261079.html 题目传送门 - 洛谷P3959 题目传送门 - Vijos P2032 题意 给定一个 ...
随机推荐
- python-小知识点-14
''' python2 python3 ''' #python2 print() print 'abc' range() xrange() 生成器 raw_input() #python3 print ...
- 第二次作业 对VC++6.0编译软件的评价
首先这个软件伴随着我们很长时间了,它是我们一上大学最先接触的,也是应用相当多的一个软件,其实在最初的时候,我对编译软件的理解非常有限,觉得它能实现一个代码的功能十分神奇的一件事情,虽然彼时我们写的代码 ...
- Week 2 代码规范
Question 1: 这些规范都是官僚制度下产生的浪费大家的编程时间.影响人们开发效率, 浪费时间的东西. My opinion: 我认为恰恰相反,这个可以提高人们的开发效率. 在团队合作当中,如果 ...
- 第三个spring冲刺第8天
今天,我们忙于完成精美的背景,还有难度的具体设置,如何达到最理想化,为此我们今天主要是做了开会讨论,但还没有完全确定好结论,明天就应该能做出结论,然后修改后台的难度设置了.
- NFV论文集(一)
一 文章名称:Throughput Maximization and Resource Optimization in NFV-Enabled Networks 发表时间:2017 期刊来源:ICC: ...
- myBatis插件(plugins)
MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用.默认情况下,MyBatis 允许使用插件来拦截的方法调用包括: Executor (update, query, flushState ...
- FreeMaker使用HashMap
private Map<String, Object> variables; <input type="hidden" id="tongzhisbm&q ...
- Bootstrap Validator使用特性,动态(Dynamic)添加的input的验证问题
http://1000hz.github.io/bootstrap-validator/#validator-usage Validated fields By default, the valida ...
- 服务器RAID设置以及简单理解
备注: 适用于测试环境,生产环境暂时未验证 1. RAID种类 最高性能的RAID0 完全拆分所有的IO 不进行校验 但是单盘损坏, 数据完全丢失 最高损耗的RAID1 损失一半的存储容量, 做镜像, ...
- Windows 聆听 简单使用体验
1. 点击windows 按键 输入语音 按照操作 选择语音 并且读出那一段话. 2. 可以将windows 语音识别 添加到开始面板 3. 使用时 点击 该图标,然后点击麦克风按钮 聆听效果如图示 ...