POJ 1080
题意:给出2列字符串,然后给出每对字符所含的值,要求你在字符之间添加 “-” 号使2组字符长度相等,然后每个相同位置字符为一对,计算值的总和,要求总和要最大。
设dp[ i ][ j ]为以a字符第i位置为结束和以b字符j位置为结束的最优解。
状态转移方程:
dp[ i ][ j ]=max( dp[ i-1 ][ j-1 ]+maps[ a[ i ] ][ b[ j ] ] , dp[ i-1 ][ j ]+maps[ '-' ][ a[ i ] ], dp[ i ][ j-1 ]+maps[ '-' ][ b[ i ] ] );//maps[ x ][ y ]为2字符的值。
mpas表打错了一个·····坑爹啊,找了很久才找得到,不算难的DP,原理大概跟最长公共字串一样,不够熟练,磨了一段时间才构建出来。
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stdio.h>
#include<string>
#include<cstring>
using namespace std;
#define N 105
int dp[N][N];
char a[N],b[N];
int maps[N][N];
int la,lb;
void deal()
{
maps['A']['A']=5;
maps['A']['C']=maps['C']['A']=-1;
maps['A']['G']=maps['G']['A']=-2;
maps['A']['T']=maps['T']['A']=-1;
maps['A']['-']=maps['-']['A']=-3;
maps['C']['C']=5;
maps['C']['G']=maps['G']['C']=-3;
maps['C']['T']=maps['T']['C']=-2;
maps['C']['-']=maps['-']['C']=-4;
maps['G']['G']=5;
maps['G']['T']=maps['T']['G']=-2;
maps['G']['-']=maps['-']['G']=-2;
maps['T']['T']=5;
maps['T']['-']=maps['-']['T']=-1;
}
void move(char *x)
{
for(int i=104;i>=0;i--)
{
x[i]=x[i-1];
}
}
int main()
{
deal();
int t;
cin>>t;
while(t--)
{
cin>>la;
if(la!=0)
cin>>a;
cin>>lb;
if(lb!=0)
cin>>b;
memset(dp,0,sizeof(dp));
move(a);
move(b);
for(int i=1;i<=la;i++)
dp[i][0]=dp[i-1][0]+maps['-'][a[i]];
for(int i=1;i<=lb;i++)
dp[0][i]=dp[0][i-1]+maps['-'][b[i]];
for(int i=1;i<=la;i++)
{
for(int j=1;j<=lb;j++)
{
// cout<<a[i]<<' '<<b[i]<<' '<<maps[a[i]][b[j]]<<endl;
dp[i][j]=dp[i-1][j-1]+maps[a[i]][b[j]];
dp[i][j]=max(dp[i-1][j]+maps[a[i]]['-'],dp[i][j]);
dp[i][j]=max(dp[i][j-1]+maps[b[j]]['-'],dp[i][j]);
}
}
/* for(int i=0;i<=la;i++)
{
for(int j=0;j<=lb;j++)
{
if(j)
cout<<" ";
cout<<dp[i][j];
}
cout<<endl;
}*/
cout<<dp[la][lb]<<endl;
}
return 0;
}