北大ACM poj1080 Human Gene Functions

/**
观察题目给出的一个最优解:
AGTGATG
-GTTA-G
将其从某一处切开,如果左边部分的分值不是最大,那么将其进行调整,
使其分值变大,则整个解分值变大,与已知的最优矛盾。
所以左边部分的分值必是最大。同理,右边也是。
可见满足最优子结构的性质。考虑使用DP:

设两个DNA序列分别为s1,s2,长度分别为len1,len2,score为分值表。
f[i,j]表示子串s1[1..i]和s2[1..j]的分值。考虑一个f[i,j],我们有:
1.s1取第i个字母,s2取“-”:f[i-1,j] + score[s1[i],'-']
2.s1取“-”,s2取第j个字母:f[i,j-1] + score['-',s2[j]]
3.s1取第i个字母,s2取第j个字母:f[i-1,j-1] + score[s1[i],s2[j]]
即f[i,j] = max(f[i-1,j] + score[s1[i],'-'], f[i,j-1] + score['-',
                s2[j]], f[i-1,j-1] + score[s1[i],s2[j]]);

然后考虑边界条件,这道题为i或j为0的情况。
当i=j=0时,即为f[0,0],这是在计算f[1,1]时用到的,
根据f[1,1] = f[0,0] + score[s1[i], s2[j]],明显有f[0,0] = 0。
当i=0时,即为f[0,1..len2],有了f[0,0],可以用f[0,j] = f[0,j-1] + table['-',s2[j]]来计算。
当j=0时,即为f[1..len1,0],有了f[0,0],可以用f[i,0] = f[i-1,0] + table[s1[i],'-']来计算。

至于计算顺序,只要保证计算f[i,j]的时候,
使用到的f[i-1,j],f[i,j-1],f[i-1,j-1]都计算出来了就行了。
所谓划分阶段也就是为了达到这个目的。这样我们使用一个二重循环就可以了。
*/

/**
以 AGTGATG 和 GTTAG 为例
    A   G   T   G   A   T   G
    0   2   3   2   0   3   2
    G   T   T   A   G
    2   3   3   0   2

            0       1       2       3       4       5
    -------------------------------------------------
                    -      --     ---    ----   -----
                    G      GT     GTT    GTTA   GTTAG
    0       0      -2      -3      -4      -7      -9
    -------------------------------------------------
            A       A      -A     --A    ---A   ---A-
            -       G      GT     GTT    GTTA   GTTAG
    1      -3      -2      -3      -4       1      -1
    -------------------------------------------------
           AG      AG     AG-    AG--   ---A-   ---AG
           --      -G     -GT    -GTT   GTTAG   GTTAG
    2      -5       2       1       0      -1       6
    -------------------------------------------------
          AGT     AGT     AGT    AGT-   AGT--  ---AGT
          ---     -G-     -GT    -GTT   -GTTA  GTTAG-
    3      -6       1       7       6       3       5
    -------------------------------------------------
         AGTG    AGTG    AGTG    AGTG   AGT-G  AGT--G
         ----    -G-T    -GT-    -GTT   -GTTA  -GTTAG
    4      -8      -1       5       5       4       8
    -------------------------------------------------
        AGTGA   AGTGA   AGTGA   AGTGA   AGTGA  AGTGA-
        -----   -G-T-   -GT--   -GT-T   -GTTA  -GTTAG
    5     -11      -4       2       4      10       8
    -------------------------------------------------
       AGTGAT  AGTGAT  AGTGAT  AGTGAT  AGTGAT  AGTGAT
       ------  -G-T--  -G-T-T  -GT--T  -GTTA-  -GTTAG
    6     -12      -5       1       7       9       8
    -------------------------------------------------
      AGTGATG AGTGATG AGTGATG AGTGATG AGTGATG AGTGATG
      ------- ------G -G-T-T- -GT--T- -GTTA-- -GTTA-G
    7     -14      -7      -1       5       7      14
    -------------------------------------------------


*/
#include<stdio.h>
void change(char s[],int d[],int len){
    int i;
    for(i=0;i<len;i++){
        if(s[i]=='A')d[i]=0;
        else if(s[i]=='C')d[i]=1;
        else if(s[i]=='G')d[i]=2;
        else if(s[i]=='T')d[i]=3;
    }
}
int max(int a,int b,int c){
    int i;
    i=a>b?a:b;
    return i>c?i:c;
}
int main(){
    int score[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 f[201][201],d1[101],d2[101];
    int test,len1,len2,i,j;
    char s1[101],s2[101];
    int a,b,c;
    //freopen("in.txt","r",stdin);
    scanf("%d",&test);
    while(test--){
        scanf("%d%s",&len1,s1);
        change(s1,d1,len1);
        scanf("%d%s",&len2,s2);
        change(s2,d2,len2);
        for(i=0;i<=len1;i++){
            for(j=0;j<=len2;j++){
                if(i==0&&j){
                    f[0][j]=f[0][j-1]+score[4][d2[j-1]];
                }
                else if(i==0&&j==0){
                    f[0][0]=0;
                }
                else if(i&&j==0){
                    f[i][0]=f[i-1][0]+score[d1[i-1]][4];
                }
                else{
                    a=f[i-1][j]+score[d1[i-1]][4];
                    b=f[i][j-1]+score[4][d2[j-1]];
                    c=f[i-1][j-1]+score[d1[i-1]][d2[j-1]];
                    f[i][j]=max(a,b,c);
                }
            }
        }
        printf("%d\n",f[len1][len2]);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值