这题的题意看了20min才看懂,一直以为那个5*5的表格是上面两个序列匹配的结果推出来的,然后下面的结果是那个5*5的表格推出来的............
题目还是很简单的,有些类似LCS。dp[i][j]表示第一个序列匹配到i,第二个序列匹配到j,产生的最大相似度。然后转移的时候考虑,有三个情况,第一个序列这个位置用-和第二个序列的匹配,第二个序列这个位置用-和第一个序列的匹配,两个序列这个位置不用-,强行匹配。记忆化搜索一下就可以了。第一种就是,dp[i][j] = dp[i - 1][j] + val[-][s2[j]],第二种是dp[i][j] = dp[i][j - 1] + val[s1[i]][-],第三种是dp[i][j] = dp[i - 1][j - 1] + val[s1[i]][s2[j]]。
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 int l[3]; 5 int dp[120][120],val[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}}; 6 bool vis[120][120]; 7 char s[3][120]; 8 int dfs(int x,int y) 9 { 10 if (vis[x][y] == true || x == 0 || y == 0) 11 return dp[x][y]; 12 vis[x][y] = true; 13 int res = dfs(x,y - 1) + val[4][s[2][y]]; 14 res = max(res,dfs(x - 1,y) + val[s[1][x]][4]); 15 res = max(res,dfs(x - 1,y - 1) + val[s[1][x]][s[2][y]]); 16 return dp[x][y] = res; 17 } 18 int main() 19 { 20 scanf("%d",&l[1]); 21 scanf("%s",s[1] + 1); 22 scanf("%d",&l[2]); 23 scanf("%s",s[2] + 1); 24 for (int o = 1;o <= 2;o++) 25 for (int i = 1;i <= l[o];i++) 26 if (s[o][i] == 'A') 27 s[o][i] = 0; 28 else if (s[o][i] == 'C') 29 s[o][i] = 1; 30 else if (s[o][i] == 'G') 31 s[o][i] = 2; 32 else 33 s[o][i] = 3; 34 for (int i = 1;i <= l[1];i++) 35 dp[i][0] = dp[i - 1][0] + val[s[1][i]][4]; 36 for (int i = 1;i <= l[2];i++) 37 dp[0][i] = dp[0][i - 1] + val[4][s[2][i]]; 38 printf("%d ",dfs(l[1],l[2])); 39 return 0; 40 }