http://acm.hdu.edu.cn/showproblem.php?pid=1080
难得徒手撸一题dp……
并不能是lcs,只能是有点像
刚看到有点迷茫,比较自然地确定一个状态dp[i][j],表示处理到串a的i位,串b的j位
然而存在着一个’-‘的设定……
先假定为dp[i][j]指的结果的是对齐了的,有一方的结尾是’-‘或者都不是’-‘
对于一个状态i,j来说,可以从i-1,j-1或者i,j-1或者i-1,j转移而来。i-1和j-1就是让ai和bj匹配,i,j-1转移则是让ai和bj-1匹配,多出来的bj和’-‘去匹配,i-1,j同理。
dp[i][j]=max(dp[i-1][j-1]+add[i][j],dp[i-1][j]+add[A[i]][‘-‘],dp[i][j-1]+add[‘-‘][B[j]])
add表示两个符号匹配的评价。
录入字符串的时候转化为数字,这样处理起来方便点。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int add[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,-99999
};
int dp[111][111];
void process(char* start,int n)
{
for (int i=0;i<n;i++)
{
if (start[i]=='A')
start[i]=0;
if (start[i]=='C')
start[i]=1;
if (start[i]=='G')
start[i]=2;
if (start[i]=='T')
start[i]=3;
}
}
int main()
{
char A[111],B[111];
int ALen,BLen;
int Total;
cin.sync_with_stdio(false);
cin>>Total;
for (int C=0;C<Total;C++)
{
cin>>ALen>>A+1>>BLen>>B+1;
process(A+1,ALen);
process(B+1,BLen);
//注意初始化![i][0]表示i个'-'和前i个字母对
dp[0][0]=0;
for (int i=1;i<=ALen;i++)
{
dp[i][0]=add[A[i]][4]+dp[i-1][0];
}
for (int i=1;i<=BLen;i++)
{
dp[0][i]=add[B[i]][4]+dp[0][i-1];
}
for (int i=1;i<=ALen;i++)
{
for (int j=1;j<=BLen;j++)
{
int result(dp[i-1][j-1]+add[A[i]][B[j]]);
result=max(result,dp[i-1][j]+add[A[i]][4]);
result=max(result,dp[i][j-1]+add[4][B[j]]);
dp[i][j]=result;
}
}
cout<<dp[ALen][BLen]<<endl;
}
return 0;
}