POJ1080 - DP(LCS变种)

 这道通过率超过50%的题居然折腾了我一下午...仔细想一下首先就是题意没有理解清楚...开始自己推了一个DP...即:

    首先判断s1与s2的长度...如果一样..则直接输出...如果strlen(s2)>strlen(s1)则把s1与s2换一下..

    用a[ i ] [ j ] 数组来存状态..储存的状态是s1的前i个数中插了j个'-'..

   状态转移则是 : a[ i ] [ j ] = max ( a[ i ] [ j - 1 ] + turn ( s1[ i ]  ,  s2[ i - j ] )   ,  a [ i -1 ] [ j -1 ]  + turn ( s1 [ i ] , ' - ' ) )     (    1 <= i <= strlen(s1)   ,  0 < = j < = strlen(s1) - strlen(s2) )

 交上去WA~~测了N个数据..终于发现BUG..没有考虑到:

      2 AT

      2 TA   

这类情况...最优解应该是   -AT 与 TA-  ... 但我开始的思路当两个串相等就直接求值~~~即AT直接与TA对应求值....出错的原因就是我完全没考虑到两个数组有可能都存在'-'的情况.

在最初的DP上加了很多条件和判断..希望能用最开始的DP调出来..但一直在WA....最后还是去看了Discuss了....这题正确的DP方程实在是美妙...自己的思维还是太死板了..根本没有想到那一步来..关于状态转移方程就ctrl + c , ctrl + v贴在下面...也提醒自己做DP的时候思维一定要放开...切中状态转移方程.. :

     c[i][j]=max{c[i-1][j-1]+mat(a[i],b[j]),c[i][j-1]+mat('-',b[j]),c[i-1][j]+mat(a[i],'-')}        (其中mat(x,y)表示字符x与y匹配的权值)
    则有上述状态转移方程可得边界为:
           c[0][0]=0
           c[i][0]=c[i-1][0]+mat(a[i],'-')
           c[0][j]=c[0][j-1]+mat('-',b[j])

DP搞了一个星期还是这个样子~~要继续努力了~~一些经典的状态转移方程也要整理下....


program : 


#include<iostream>
using namespace std;
int t,l1,l2;
char s1[301],s2[301];
int turn(char a,char b)
{
    if (a=='A')
    {
       if (b=='A') return 5;   if (b=='C') return -1;
       if (b=='G') return -2;  if (b=='T') return -1;
       if (b=='-') return -3;                    
    }
    if (a=='C')
    {
       if (b=='A') return -1;  if (b=='C') return 5;
       if (b=='G') return -3;  if (b=='T') return -2;
       if (b=='-') return -4;                     
    }
    if (a=='G')
    {
       if (b=='A') return -2;  if (b=='C') return -3;
       if (b=='G') return 5;   if (b=='T') return -2;
       if (b=='-') return -2;                     
    }    
    if (a=='T')
    {
       if (b=='A') return -1;  if (b=='C') return -2;
       if (b=='G') return -2;  if (b=='T') return 5;
       if (b=='-') return -1;                     
    }    
    if (a=='-')
    {
       if (b=='A') return -3;  if (b=='C') return -4;
       if (b=='G') return -2;  if (b=='T') return -1;
       if (b=='-') return -1;                    
    }    
}
int mmax(int a,int b,int c)
{
    if ( a>b && a>c ) return a;
    if ( b>c ) return b;
    return c;   
}
int DP()
{
    int a[101][101],i,j,kans=0;
    memset(a,0,sizeof(a));
    for (i=1;i<=l1;i++) a[i][0]=a[i-1][0]+turn(s1[i],'-');
    for (i=1;i<=l2;i++) a[0][i]=a[0][i-1]+turn('-',s2[i]);
    for (i=1;i<=l1;i++)
     for (j=1;j<=l2;j++)
       a[i][j]=mmax(a[i-1][j-1]+turn(s1[i],s2[j]),a[i-1][j]+turn(s1[i],'-'),a[i][j-1]+turn('-',s2[j]));       
    return a[l1][l2];
}
int main()
{
    scanf("%d",&t);
    while (t--)
    {
          for (int i=1;i<=300;i++) { s1[i]='-'; s2[i]='-'; }
          scanf("%d",&l1);
          for (int i=0;i<=l1;i++) scanf("%c",&s1[i]);
          scanf("%d",&l2);
          for (int i=0;i<=l2;i++) scanf("%c",&s2[i]);
          printf("%d\n",DP());    
    }
    return 0;   
}


你可能感兴趣的:(c)