相似基因

也同样是被动态规划玩坏的一天

题目链接:https://www.luogu.com.cn/problem/P1140
题目来自洛谷普及/提高-

题目描述:

两个基因的相似度的计算方法如下:

对于两个已知基因,例如AGTGATG和GTTAG,将它们的碱基互相对应。当然,中间可以加入一些空碱基-,例如:在这里插入图片描述
这样,两个基因之间的相似度就可以用碱基之间相似度的总和来描述,碱基之间的相似度如下表所示:
在这里插入图片描述
计算得到相似度为9,也可以再排列为
在这里插入图片描述
相似度为14.规定两个基因的相似度为所有对应方法中,相似度最大的那个。

输入输出格式:不码字了。。。看图

在这里插入图片描述

反复分析:

对于动态规划,最重要的就是找到它的状态转移方程,这时候首先考虑的就是这个状态从哪里来又支配了后面的哪一个状态。例如在此题中,有三种状态可供跳转 0<i<len(a) ; 0<j<len(b)

  1. 尝试在字符串 a 加空格, 让 b 当前一位与空格匹配:dp[i][j-1]+v[4][b[j]]
  2. 尝试在字符串 b 加空格, 让 a 当前一位与空格匹配:dp[i-1][j]+v[a[i]][4]
  3. 最后假设不加空格的额情况:dp[i-1][j-1]+v[a[i]][b[j]]

三种情况找到最大然后重复转移状态

实现

#include<iostream>
#include<algorithm>
#include<cstdio>
#define maxn 200
using namespace std;
int dp[maxn][maxn];
int a[maxn], b[maxn];
int la, lb;
int v[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() {
	cin>>la;
	for(int i=1; i<=la; i++) {
		char x; cin>>x;
		if(x=='A') a[i]=0; 
		if(x=='C') a[i]=1;
		if(x=='G') a[i]=2; 
		if(x=='T') a[i]=3;
	}
	cin>>lb;
	for(int i=1; i<=lb; i++) {
		char x; cin>>x;
		if(x=='A') b[i]=0; 
		if(x=='C') b[i]=1;
		if(x=='G') b[i]=2; 
		if(x=='T') b[i]=3;
	}
	for(int i=1;i<=la;i++) for(int j=1;j<=lb;j++) dp[i][j]=-2e8;
	//当出现某一空串时 
	for(int i=1; i<=la; i++) dp[i][0]=dp[i-1][0]+v[a[i]][4];
	for(int i=1; i<=lb; i++) dp[0][i]=dp[0][i-1]+v[4][b[i]];
	//开始状态转移
	for(int i=1; i<=la; i++) {
		for(int j=1; j<=lb; j++) {
			//尝试 la 加空格
			//让 lb的倒 2位与 la的最后一位匹配
			// lb的最后一位与加入 la的空格匹配 
			dp[i][j]=max(dp[i][j], dp[i][j-1]+v[4][b[j]]);
			dp[i][j]=max(dp[i][j], dp[i-1][j]+v[a[i]][4]);
			dp[i][j]=max(dp[i][j], dp[i-1][j-1]+v[a[i]][b[j]]);
		}
	} 
	cout<<dp[la][lb];
	return 0;
} 
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值