• [HNOI2002]DNA分子的最佳比对


    看着网上没有人写这道题的博客,洛谷上也只有十几个人AC,我不妨尝试了这道题!

    题解基本没有!

    任何一个伟大的思想,都有一个微不足道的开始。

    题目描述

    DNA分子是人类遗传信息的载体,它间接地指导蛋白质的合成。DNA分子是由四种核苷酸组成的长链,这四种核苷酸分别是腺嘌呤核苷酸(用A代表)、鸟嘌呤核苷酸(用G代表)、胞嘧啶核苷酸(用C代表)和胸腺嘧啶核苷酸(用T代表)。习惯上用一个字符集为{A,T,C,G}的字符串来表示一个DNA分子序列,如CGTTAGA。

    在生物进化过程中,DNA分子可能发生各种各样的突变。这种突变形成了生物遗传信息的改变,从而使生物得以分化,构成了生物的多样性。主要的突变有三种:(1)在一个DNA序列中插入一个新的核苷酸,(2)DNA序列中丢失了一个核苷酸,(3)DNA序列中的某个核苷酸被另一个核苷酸所取代。

    所谓两个DNA序列的一个比对是寻找一种排列方式,使得两个DNA序列在同样的位置上有相同的核苷酸,而若在同样的位置上两个DNA序列的核苷酸不同,则是由三种突变之一得到。例如,对两个DNA序列T =ATCAG,T =ACTAG,可以按如下方式比对,

    比对1:

    T1 T2

    A A T --- (T2 的该位置由T1 丢失一个核苷酸T得到,“--”表示空白)

    C C

    --- T (T2 的该位置由T1 插入一个核苷酸T得到)

    A A

    G G

    也可以按如下方式比对

    比对2:

    T1 T2

    A A

    T C (T2 的该位置用一个C取代 T1 的T)

    C T (T2 的该位置用一个T1取代T 的C)

    A A

    G G

    如果两个DNA序列在相同的位置上有越多相同的核苷酸对,则表明它们之间越相似,即它们存在功能上的相似性和进化史上的亲缘关系。

    对于两个DNA序列的一个比对,规定如下得分方式:(1)一个同样的位置上有相同的核苷酸对,则可得1分;(2)一个同样的位置上有不同的核苷酸对,则得0分;(3)如果在某个位置上一个序列有核苷酸,而另一个序列在该位置上为“--”,则得-2分。例如,比对1的得分是0分,比对2的得分是3分。

    问题是:对于两个DNA序列,寻找一种比对方式,使得它们的得分最高。

    输入输出格式

    输入格式:

    输入数据由文件名为INPUT.*的文本文件提供,共有2行。

    第1行为DNA序列T1 , 第2行为DNA序列T2 。序列的长度不大于1000。序列中的字母是英文小写或者大写字母。

    输出格式:

    程序运行结束时,在屏幕上输出所找出的最大的得分

    输入输出样例

    输入样例: 
    Atcag
    Actag
    
    输出样例: 
    3



    这道题我调了好久才调出来,悲惨qwq

    讲一讲思路吧!
    正经点!

    这道题要懂,恐怕LCS算法也要懂,链接:https://www.cnblogs.com/wangshengjun/p/LCS.html
    这是比LCS多一点复杂一点。
    f[i][j]表示第一个字符匹配到i的,第二个字符匹配到j的最优值。
    f[i][j]有三种情况转移:
    第一种是 i 不变 ,j 向后移一格 , 则值 减二。(如题:如果在某个位置上一个序列有核苷酸,而另一个序列在该位置上为“--”,则得-2分。例如,比对1的得分是0分,比对2的得分是3分。)
    代码如下:
    f[i][j-1]-2
    
              第二种是 j不变,i向后移一格,则值减二。(如题:如果在某个位置上一个序列有核苷酸,而另一个序列在该位置上为“--”,则得-2分。例如,比对1的得分是0分,比对2的得分是3分。)
    代码如下:
    f[i-1][j]-2
    

                                 第三种是i,j 同时向后移一格,当两串相同时+1,否则,不更新值。

                                      代码如下:

    f[i-1][j-1]+(s1[i]==s2[j]?1:0)
    

            结合之后状态转移方程就产生了!

    f[i][j]=max(f[i-1][j-1]+(s1[i]==s2[j]?1:0),f[i-1][j]-2,f[i][j-1]-2)
    
                       用状态转移方程转换成二维图:
                                                            
          但还需要预处理一下,把f[i][j]的初始值赋值为(0,-2,-4,-6,-8 ,......(如此规律));
                            人间就是这么简单,这么奇怪!

                            加上之后,万事大吉了— — AC 了。

    70~70~70~ WA了3个点。

                  

              最后,废话不多说,放代码!!!

                              

    #include<bits/stdc++.h>
    int f[1039][1039],ans=-2147483648,flag;
    char s1[1039],s2[1039];
    int max(int a,int b,int c){return std::max(a,std::max(b,c));}
    int main(){
        scanf("%s%s",s1+1,s2+1);
        int l1=strlen(s1+1);int l2=strlen(s2+1),tmp=0,l = std::max(l1,l2);
        for(int i=0;i<l+1;i++){
        	f[i][0]=tmp;
        	f[0][i]=tmp;
        	tmp-=2;
    	}f[0][0] = 0;
        for(int i = 1; i < l1+1; i++)
            for(int j = 1; j < l2+1; j++){
                if(s1[i]==s2[j])flag = 1;
                else flag = 0;
                f[i][j] = max(f[i-1][j-1]+flag, f[i-1][j]-2, f[i][j-1]-2);
            }
        ans = std::max(ans, f[l1][l2]);
        printf("%d", ans);
        return 0;
    }
    

      小心字符串,很肯人的。

    难道这道题就这么难么?
    祝大家RP++!

    OVER!

           

    
    

                    

    
    
    
    

  • 相关阅读:
    whoami
    w
    id
    su
    chpasswd
    chage
    password
    scrapy框架中Download Middleware用法
    scrapy框架持久化存储
    scrapy框架中Item Pipeline用法
  • 原文地址:https://www.cnblogs.com/wangshengjun/p/P2268DNA.html
Copyright © 2020-2023  润新知