這道通過率超過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; }