洛谷 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 题意 给定一个 ...
随机推荐
- OSG 改变窗口大小
viewer.realize();//需要realize,否则窗口为null osgViewer::GraphicsWindow *pWnd = dynamic_cast<osgViewer:: ...
- leetcode: 638.大礼包
题目描述: https://leetcode-cn.com/problems/shopping-offers/ 解题思路: 这类求最大最小的问题首先想到的就是用DP求解. 这题还用到了递归,首先计算单 ...
- elastic-search-kibana-in-docker-dotnet-core-app
[翻译] 使用ElasticSearch,Kibana,ASP.NET Core和Docker可视化数据 原文地址:http://www.dotnetcurry.com/aspnet/1354/e ...
- octave基本指令4
octave基本指令4 图形化显示数据 >> t=[0:0.01:0.98]; >> y1 = sin(2*pi*4*t); %pi表示π >> plot(t,y1 ...
- octave基本指令2
octave基本指令2 数据移动 >> pwd %显示出当前路径 ans C:\Octave\3.2.4_gcc-4 >> cd 'G:\machine learning' % ...
- Python入门:如何使用第三方库?
这是关于Python的第13篇文章,也是关于<编程小白的第1本Python入门书>内容的最后一篇,主要介绍下如何使用第三方库. 1. 第三方库 Python相当于一个手机,第三方库相当于手 ...
- Eclipse集成Tomcat报错:java.lang.OutOfMemoryError: PermGen space
Eclipse集成Tomcat报错,使用Spring 4.3 框架,运行一段应用后,控制台报错: Unexpected death of background thread ContainerBack ...
- [转帖]2016年时的新闻:ASP.NET Core 1.0、ASP.NET MVC Core 1.0和Entity Framework Core 1.0
ASP.NET Core 1.0.ASP.NET MVC Core 1.0和Entity Framework Core 1.0 http://www.cnblogs.com/webapi/p/5673 ...
- 使用TensorFlow实现分类
这一节使用TF搭建一个简单的神经网络用于分类任务,首先把需要的包引入,另外为了防止在多次运行中一些图中的tensor在内存中影响实验,采取重置操作: import tensorflow as tf i ...
- python threading模块使用 以及python多线程操作的实践(使用Queue队列模块)
今天花了近乎一天的时间研究python关于多线程的问题,查看了大量源码 自己也实践了一个生产消费者模型,所以把一天的收获总结一下. 由于GIL(Global Interpreter Lock)锁的关系 ...