|
问题描述: 给出两个串,对应字母有权值,可以错位安排,使得最后总权和最大。 解题思路: 首先定义: rt[a][b] 表示字符a和字符b配对时的权值 dp[i][j] 表示第一个串到i和第二个串到j两个子串所组合出的最大权和为dp[i][j]; 1)如果第i个字符和第j个字符配对,那么dp[i][j] = dp[i-1][j-1] + rt[str1[i]][str2[j]]; 2)如果第一个串的第i个字符和'-'配对, 那么dp[i][j] = dp[i-1][j] + rt[str1[i]]['-']; 3)如果第二个串的第j个字符和'-'配对,那么dp[i][j] = dp[i][j-1] + rt['-'][str2[j]]; 于是dp[i][j] = max{ dp[i-1][j-1] + rt[str1[i]][str2[j]], dp[i-1][j] + rt[str1[i]]['-'], dp[i][j-1] + rt['-'][str2[j]] }; 核心代码: #include <iostream>

using namespace std;

int dp[110][110];
char str[2][110];
int len[2];
int i, j;

 int rt[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, 0}
};

 int num(char c) {
if(c == 'A')
return 0;
if(c == 'C')
return 1;
if(c == 'G')
return 2;
if(c == 'T')
return 3;
return 4;
}

 int Max(int a, int b, int c) {
if(c > b) b = c;
return a > b ? a : b;
}

int main()
  {
int t;
scanf("%d", &t);
 while(t--) {
 for(i = 0; i < 2; i++) {
scanf("%d", &len[i]);
scanf("%s", &str[i][1]);
}

dp[0][0] = 0;
 for(i = 1; i <= len[0]; i++) {
dp[i][0] = dp[i-1][0] + rt[ num(str[0][i]) ][num('-')];
}

 for(i = 1; i <= len[1]; i++) {
dp[0][i] = dp[0][i-1] + rt[ num('-') ][ num(str[1][i]) ];
}

 for(i = 1; i <= len[0]; i++) {
 for(j = 1; j <= len[1]; j++) {
dp[i][j] = Max(
dp[i-1][j-1] + rt[ num(str[0][i]) ][num(str[1][j])],
dp[i-1][j] + rt[ num(str[0][i]) ][ num('-') ],
dp[i][j-1] + rt[ num('-') ][ num(str[1][j]) ]
);
}
}
printf("%d\n", dp[ len[0] ][ len[1] ]);
}
}

|