• LuoguP4059 找爸爸-序列DP


    容我吐槽一波题目名字。。

    首先我们考虑如果没有空格连续产生代价这一额外条件,那么是不是很好做。

    因为我们注意到,不管怎么放空格,我们最终都是把两个串匹配完了。

    同时,同一位置上下都放空格是完全没有意义的。

    所以我们直接设f[i][j]表示第一个匹配到了i,第二个匹配到了j。

    那么转移就是f[i][j]=max {f[i][j-1], f[j][i-1], f[i-1][j-1]+d[i][j]}。

    然而这里多了一个条件。。那该怎么做呢??

    同样的,我们仍然容易发现,同一位置上下都放空格不会是结果更优。

    那么对于我们就可以把这个求额外贡献的式子拆成:

    第一个0就减a,以后的连起来的0都减b。

    在此基础上,我们考虑设f[i][j][0/1/2]表示第一个匹配到了i,第二个匹配到了j,且此时末尾(没有/第一个串/第二个串)出现了0。

    那么的话,转移就很简单了:

           f[i][j][0]=max (f[i-1][j-1][0], max (f[i-1][j-1][1], f[i-1][j-1][2]))+d[ad[i]][bd[j]];
                f[i][j][1]=max (f[i][j-1][0], f[i][j-1][2])-a;
                f[i][j][1]=max (f[i][j][1], f[i][j-1][1]-b);
                f[i][j][2]=max (f[i-1][j][0], f[i-1][j][1])-a;
                f[i][j][2]=max (f[i][j][2], f[i-1][j][2]-b);

    最后稍微注意下边界就好了。。

    #include <bits/stdc++.h>
    using namespace std;
    inline int gi () {
        int x=0,w=0; char ch=0;
        while (!(ch>='0' && ch<='9')) {if (ch=='-') w=1; ch=getchar ();}
        while (ch>='0' && ch<='9') x= (x<<3)+(x<<1)+(ch^48), ch=getchar ();
        return w?-x:x;
    }
    
    #define RG register
    
    const int N=3010;
    
    char ADNA[N],BDNA[N];
    int a,b,alen,blen,ad[N],bd[N],d[5][5],f[N][N][3];
    
    int main ()
    {
        RG int i,j;
        scanf ("%s%s", ADNA+1, BDNA+1);
        for (i=1;i<=4;++i)
            for (j=1;j<=4;++j)
                d[i][j]=gi ();
        a=gi (), b=gi ();
        alen=strlen (ADNA+1), blen=strlen (BDNA+1);
        for (i=1;i<=alen;++i) 
            switch (ADNA[i]) {
                case 'A': ad[i]=1; break;
                case 'T': ad[i]=2; break;
                case 'G': ad[i]=3; break;
                case 'C': ad[i]=4; break;
            }
        for (i=1;i<=blen;++i) 
             switch (BDNA[i]) {
                case 'A': bd[i]=1; break;
                case 'T': bd[i]=2; break;
                case 'G': bd[i]=3; break;
                case 'C': bd[i]=4; break;
            }
        memset (f, 0xcf, sizeof (f));
        f[0][0][0]=0, f[0][1][1]=f[1][0][2]=-a;
        for (i=1;i<=alen;++i)
            for (j=1;j<=blen;++j) {
                f[i][j][0]=max (f[i-1][j-1][0], max (f[i-1][j-1][1], f[i-1][j-1][2]))+d[ad[i]][bd[j]];
                f[i][j][1]=max (f[i][j-1][0], f[i][j-1][2])-a;
                f[i][j][1]=max (f[i][j][1], f[i][j-1][1]-b);
                f[i][j][2]=max (f[i-1][j][0], f[i-1][j][1])-a;
                f[i][j][2]=max (f[i][j][2], f[i-1][j][2]-b);
            }
        printf ("%d
    ", max (f[alen][blen][0], max (f[alen][blen][1], f[alen][blen][2])));
        return 0;
    }

     

  • 相关阅读:
    [转]Java连接oracle数据库实例
    class.forname().newInstance()
    使用jdbc调用Oracle报错:ORA00911 无效字符
    使用HttpWebRequest需要设置Accept和UserAgent属性
    IIS应用程序池(进程池)假死问题解决办法
    windows调试工具集
    广东电信最新DNS更新了
    Web2.0样式
    一个开源的flash幻灯片展示源码文件
    Microsoft Visio2003 简体中文版 下载
  • 原文地址:https://www.cnblogs.com/Bhllx/p/9833647.html
Copyright © 2020-2023  润新知