題目大意:
給兩個由A、C、T、G四個字符組成的字符串,可以在兩串中加入-,使得兩串長度相等。
每兩個字符匹配時都有個值,求怎樣安排使得總的值最大,兩個-不能匹配。
解題思路:
這題轉化一下就是一個裸的最長公共子串問題,只不過要求匹配時長度一樣。
dp[i][j]表示第一串的第前i個字符和第二串的前j個字符匹配時,能達到的最大值。
初始化時注意dp[0][j]和dp[j][0]不能為零,為相應字符與-匹配時的總和。
代碼:
<SPAN style="FONT-SIZE: 14px">#include<iostream> #include<cmath> #include<cstdio> #include<cstdlib> #include<string> #include<cstring> #include<algorithm> #include<vector> #include<map> #include<set> #include<stack> #include<list> #include<queue> #define eps 1e-6 #define INF 0x1f1f1f1f #define PI acos(-1.0) #define ll __int64 #define lson l,m,(rt<<1) #define rson m+1,r,(rt<<1)|1 //#pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; /* freopen("data.in","r",stdin); freopen("data.out","w",stdout); */ #define Maxn 110 map<char,int>myp; int mar[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,-INF}}; //存入值表 char sa1[Maxn],sa2[Maxn]; int a[Maxn],b[Maxn]; int dp[Maxn][Maxn]; int main() { myp['A']=0,myp['C']=1,myp['G']=2,myp['T']=3,myp['-']=4; //將字符和表映射起來 int t,len1,len2; scanf("%d",&t); while(t--) { scanf("%d%s",&len1,sa1+1); for(int i=1;i<=len1;i++) a[i]=myp[sa1[i]]; //轉化成相應的代表數字 scanf("%d%s",&len2,sa2+1); for(int i=1;i<=len2;i++) b[i]=myp[sa2[i]]; memset(dp,-INF,sizeof(dp)); dp[0][0]=0; for(int i=1;i<=len1;i++) //注意初始化時 是和-匹配 dp[i][0]=dp[i-1][0]+mar[a[i]][4]; // printf("i:%d j:%d %d\n",i,0,dp[i][0]); for(int j=1;j<=len2;j++) dp[0][j]=dp[0][j-1]+mar[b[j]][4]; //printf("i:%d j:%d %d\n",0,j,dp[0][j]); // putchar('\n'); for(int i=1;i<=len1;i++) for(int j=1;j<=len2;j++) { int Mx=dp[i][j]; Mx=max(Mx,dp[i-1][j-1]+mar[a[i]][b[j]]); //i-j匹配 Mx=max(Mx,max(dp[i-1][j]+mar[a[i]][4],dp[i][j-1]+mar[b[j]][4])); //(j和i-1,i和-)匹配 (i和j-1,-和j)匹配 Mx=max(Mx,dp[i-1][j-1]+mar[a[i]][4]+mar[b[i]][4]); //兩個都匹配- dp[i][j]=Mx; //printf("i:%d j:%d %d\n",i,j,dp[i][j]); } printf("%d\n",dp[len1][len2]); } return 0; } </SPAN>