POJ-1080- Human Gene Functions-DP-LCS变形

本文探讨如何使用动态规划算法解决序列匹配问题,通过构建最优路径实现序列间的最佳匹配,利用状态转移方程和边界初始化策略求解最优解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

给出两个序列,可以任意往他们之间插入‘-’, 求等长度后,按照给出的表计算得到的sum

可知,尽可能让相同的字母对齐才会得到最优的sum,

也就是看他们有多少字母相同,类似LCS

dp方程类似LCS:

if(a[i]==b[j])
					dp[i][j]=dp[i-1][j-1]+get(i,j);  //相等的情况就是让他们2个对齐
					else //否则就看是否要插入‘-’,以及插入在上面还是在下面
						dp[i][j]=max(dp[i-1][j-1]+get(i,j),dp[i-1][j]+get(i,'-'),dp[i][j-1]+get('-',j));



要注意的问题就是  【边界的初始化】;



#include <cmath>
#include <cstdio>
#include <cstring>
#include <limits>
#include <string>
#include <iostream>
#include <list>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>  
using namespace std;  
const int inf=2147483647;

int min(int a,int b){return a<b?a:b;}
int min(int a,int b,int c){return min(min(a,b),c);} 
int max(int a,int b){return a>b?a:b;}
int max(int a,int b ,int c){return max(max(a,b),c);}

char tm[200];
char nm[200];
char *a,*b;
int get(int j,char aa)
{
		if (a[j]=='A') return -3;
		if (a[j]=='C') return -4;
		if (a[j]=='G') return -2;
		if (a[j]=='T') return -1; 
		return 0;

} 
int get(char aa,int j)
{
		if (b[j]=='A') return -3;
		if (b[j]=='C') return -4;
		if (b[j]=='G') return -2;
		if (b[j]=='T') return -1; 
		return 0;

}
int get(int i,int j)
{ 
	if (a[i]=='A')
	{
		if (b[j]=='A') return 5;
		if (b[j]=='C') return -1;
		if (b[j]=='G') return -2;
		if (b[j]=='T') return -1;
		if (b[j]=='-') return -3; 
	}
	if (a[i]=='C')
	{
		if (b[j]=='A') return -1;
		if (b[j]=='C') return 5;
		if (b[j]=='G') return -3;
		if (b[j]=='T') return -2;
		if (b[j]=='-') return -4; 
	}
	if (a[i]=='G')
	{
		if (b[j]=='A') return -2;
		if (b[j]=='C') return -3;
		if (b[j]=='G') return 5;
		if (b[j]=='T') return -2;
		if (b[j]=='-') return -2; 
	}
	if (a[i]=='T')
	{
		if (b[j]=='A') return -1;
		if (b[j]=='C') return -2;
		if (b[j]=='G') return -2;
		if (b[j]=='T') return 5;
		if (b[j]=='-') return -1; 
	}
	if (a[i]=='-')
				{
		if (b[j]=='A') return -3;
		if (b[j]=='C') return -4;
		if (b[j]=='G') return -2;
		if (b[j]=='T') return -1; 
				}
}
int dp[205][205];
int main()
{  
	int t;
	cin>>t;
	while(t--)
	{
		int i,j,k,h;
		int n,m;
		memset(dp,0,sizeof(dp));
		cin>>n;getchar();
		for (i=1;i<=n;i++)
			scanf("%c",&tm[i]);
		cin>>m;getchar();
		for (i=1;i<=m;i++)
			scanf("%c",&nm[i]);
		if (n<m)		//统一规定上面的序列为较长的
		{
			swap(n,m); 
			a=nm;
			b=tm;	
		}
		else
		{
			a=tm;
			b=nm;
		}
	 
		for(i=1;i<=n;i++)
			dp[i][0]=dp[i-1][0]+get(i,'-');		//当j=1时,在判断dp[i][j-1]时,表示i与j-1对齐,而在第一个序列插入‘-’与第二个序列的j对齐,
												//因为j-1已经为0了,所以意味着在前面插入了 i个'-',所以需要在这里初始化好边界条件,否则有问题.
		for (i=1;i<=m;i++)
			dp[0][i]=dp[0][i-1]+get('-',i);

		for (i=1;i<=n;i++)
		{
			for (j=1;j<=m;j++)
			{ 
				if(a[i]==b[j])
					dp[i][j]=dp[i-1][j-1]+get(i,j);  //相等的情况就是让他们2个对齐
					else //否则就看是否要插入‘-’,以及插入在上面还是在下面
						dp[i][j]=max(dp[i-1][j-1]+get(i,j),dp[i-1][j]+get(i,'-'),dp[i][j-1]+get('-',j));
			} 
		}
		printf("%d\n",dp[n][m]);
	}
	
	return 0;  
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值