P1140 相似基因

链接:https://www.luogu.com.cn/problem/P1140
题目:

思路:设置递推状态:dp[i][j]表示a的前i个碱基和b的前j个碱基配对的最大值。
那么递推:
1.ans1设置为dp[i-1][j-1]+val[a[i]][b[j]]就是说a[i]和b[j]可以凑一对,那么就凑;
2.ans2设置为dp[i-1][j]+val[0][a[i]]就是说a[i]和b的空凑一对;
3.ans3设置为dp[i][j-1]+val[0][b[j]],即b[j]与a的空凑一对。
然后取ans= max(ans1,ans2,ans3)即可
比较好的blog:https://www.luogu.com/paste/u7l8dqnn
代码:

#include<iostream>
#include<vector>
#include<algorithm>
#include<math.h>
#include<sstream>
#include<string>
#include<string.h>
#include<iomanip>
#include<stdlib.h>
#include<map>
#include<queue>
#include<limits.h>
#include<climits>
#include<fstream>
#include<stack>
typedef long long ll;
using namespace std;

const int N = 110;
ll dp[N][N];
map<char, int>mp;
ll val[5][5]={
	{INT_MIN,-3,-4,-2,-1},
	{-3,5,-1,-2,-1},
	{-4,-1,5,-3,-2},
	{-2,-2,-3,5,-2},
	{-1,-1,-2,-2,5}};
string a, b; 
ll dfs(ll ik, ll jk)
{
	if (!ik and !jk)return 0;
	if (ik == 0)
	{
		ll res = 0;
		for (int i = 0; i < jk; i++)res += val[0][mp[b[i]]];
		return dp[0][jk] = res;
	}
	if (!jk)
	{
		ll res = 0;
		for (int i = 0; i < ik; i++)res += val[0][mp[a[i]]];
		return dp[ik][0] = res;
	}
	if (dp[ik][jk])return dp[ik][jk];
	ll ans1 = dfs(ik-1,jk-1) + val[mp[a[ik - 1]]][mp[b[jk - 1]]];
	ll ans2 = dfs(ik - 1, jk) + val[mp[a[ik - 1]]][0];
	ll ans3 = dfs(ik, jk - 1) + val[mp[b[jk - 1]]][0];
	ll ans = max(ans1, max(ans2, ans3));
	return dp[ik][jk] = ans;
}
int main()
{
	int na, nb;
	cin >> na >> a >> nb >> b;
	if (a.length() < b.length())swap(a, b);
	//a.length()>=b.length()
	//dp[i][j]:a[i],b[j]
	
	mp['A'] = 1; mp['C'] = 2; mp['G'] = 3; mp['T'] = 4;
	cout << dfs(a.length(), b.length());//其实换不换都没关系,是我脑子抽了()
	return 0;
}

posted on 2024-05-15 16:25  WHUStar  阅读(1)  评论(0编辑  收藏  举报