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\n", max (f[alen][blen][0], max (f[alen][blen][1], f[alen][blen][2])));
    return 0;
}

 

posted @ 2018-10-22 22:45  薄荷凉了夏  阅读(219)  评论(2编辑  收藏  举报