• luogu 4059 [Code+#1]找爸爸 动态规划


    Description

    小A最近一直在找自己的爸爸,用什么办法呢,就是DNA比对。小A有一套自己的DNA序列比较方法,其最终目标是最
    大化两个DNA序列的相似程度,具体步骤如下:1.给出两个DNA序列,第一个长度为n,第二个长度为m。2.在两个序
    列的任意位置插入任意多的空格,使得两个字符串长度相同3.逐位进行匹配,如果两个序列相同位置上的字符都不
    是空格,假设第一个是x,第二个是y,那么他们的相似程度由d(x,y)定义。对于两个序列中任意一段极长的长度为
    k的连续空格,我们定义这段空格的相似程度为g(k)=-A-B(k-1)。那么最终两个序列的相似程度就是所有的d(x,y)
    加上所有的极长空格段的相似程度之和。现在小A通过某种奥妙重重的方式得到了小B的DNA序列中的一段,他想请
    你帮他算一下小A的DNA序列和小B的DNA序列的最大相似程度。
     

    Input

    输入第1行一个字符串,表示小A的DNA序列。
    输入第2行一个字符串,表示小B的DNA序列。
    接下来4行,每行4个整数,用空格隔开,表示d数组,
    具体顺序如下所示。
    d(A,A)d(A,T)d(A,G)d(A,C)
    d(T,A)d(T,T)d(T,G)d(T,C)
    d(G,A)d(G,T)d(G,G)d(G,C)
    d(C,A)d(C,T)d(C,G)d(C,C)
    最后一行两个用空格隔开的正整数A,B,意义如题中所述。
    对于所有测试点
    有0<B<A≤1000,-1000≤d(x,y)≤1000,d(x,y)=d(y,x),
    序列只包含{A,T,G,C}四种字符。
    N+M<=3000

    Output

    输出共一行,表示两个序列的最大相似程度

    有一个特殊的性质:
    一段长度为 $k$ 的连续空格的代价为 $-A-B(k-1)$.
    可以看成第一个空格的代价为 $-A$, 其它空格代价为 $-B$.
    那么我们就设状态 $f[i][j],g[i][j],h[i][j]$ 分别表示 $S$ 串前 $i$ 个与 $T$ 串前 $j$ 个达到长度相同,且最后一个字符分别为 字母/字母,字母/空格,空格/字母的最大相似度.
    因为不可能出现空格/空格的情况,所以就不设这个状态了.
    考虑转移:
    $f[i][j]$ :

    • $leftarrow f[i-1][j-1]+d(S[i],T[j])$.

    $g[i][j]$:

    • $leftarrow g[i-1][j]-A$.
    • $leftarrow f[i-1][j]-B$.
    • $leftarrow h[i-1][j]-A$

    $h[i][j]$:

    • $leftarrow g[i][j-1]-A$.
    • $leftarrow f[i][j-1]-A$.
    • $leftarrow h[i][j-1]-B$.
    #include <cstdio>  
    #include <cstring> 
    #include <algorithm> 
    #define N 3003  
    #define ll long long 
    #define setIO(s) freopen(s".in", "r" , stdin) 
    using namespace std;      
    char str[N];   
    int S[N], T[N], d[6][6], n, m; 
    ll f[N][N], g[N][N], h[N][N];      
    int id(char c) 
    {
        if(c == 'A') return 1; 
        if(c == 'T') return 2; 
        if(c == 'G') return 3;  
        if(c == 'C') return 4;         
    }                           
    int main() 
    {
        // setIO("input");   
        int i , j, A, B; 
        scanf("%s", str + 1), n = strlen(str + 1); 
        for(i = 1; i <= n ; ++ i) S[i] = id(str[i]);         
        scanf("%s", str + 1), m = strlen(str + 1); 
        for(i = 1; i <= m ; ++ i) T[i] = id(str[i]); 
        for(i = 1; i <= 4 ; ++ i) 
        {
            for(j = 1; j <= 4; ++j) scanf("%d", &d[i][j]);  
        }        
        scanf("%d%d", &A, &B);   
        memset(f, -63, sizeof(f)), memset(g, -63, sizeof(g)), memset(h, -63, sizeof(h));  
        g[1][0] = h[0][1] = - A, f[0][0] = 0;    
        for(i = 1; i <= n ; ++ i) 
        {
            for(j = 1; j <= m ; ++ j) 
            {     
                f[i][j] = max(f[i - 1][j - 1], max(g[i - 1][j - 1], h[i - 1][j - 1])) + d[S[i]][T[j]];        
                g[i][j] = max(max(f[i - 1][j], h[i - 1][j]) - A, g[i - 1][j] - B);    
                h[i][j] = max(max(f[i][j - 1], g[i][j - 1]) - A, h[i][j - 1] - B);     
            }
        }     
        printf("%lld
    ", max(max(f[n][m], g[n][m]), h[n][m]));      
        return 0; 
    }
    

      

  • 相关阅读:
    20170421 F110 常见问题
    BAPI_ACC_DOCUMENT_POST 解决原因代码输入问题-利用BADI
    ABAP f4帮助输入多个值
    002 MIRO发票校验采购订单项目科目分配类别检查增强-20150819
    001infor record 计划时间取值增强-20150622
    003 F-47创建预付定金请求检查增强-20150819.docx
    整理开源协议问题 GPL APACHE
    拆我的跨界手环
    ThinkPHP 的一个神秘版本 ThinkPHP 1.2
    关于 Vue 方法前面的美元符号
  • 原文地址:https://www.cnblogs.com/guangheli/p/11351280.html
Copyright © 2020-2023  润新知