1. 程式人生 > >luogu P1140 相似基因 序列DP

luogu P1140 相似基因 序列DP

algorithm ++ include class pri 題目 sin spa 一個

這題的題意看了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\n",dfs(l[1],l[2])); 39 return 0; 40 }

luogu P1140 相似基因 序列DP