P1140 相似基因 DP
阿新 • • 發佈:2019-03-12
std image aps ber long long eve code bottom html
DP好題
題目描述
兩個基因的相似度的計算方法如下:
對於兩個已知基因,例如AGTGATGAGTGATG和GTTAGGTTAG,將它們的堿基互相對應。當然,中間可以加入一些空堿基-,例如:
這樣,兩個基因之間的相似度就可以用堿基之間相似度的總和來描述,堿基之間的相似度如下表所示:
那麽相似度就是:(-3)+5+5+(-2)+(-3)+5+(-3)+5=9(−3)+5+5+(−2)+(−3)+5+(−3)+5=9。因為兩個基因的對應方法不唯一,例如又有:
相似度為:(-3)+5+5+(-2)+5+(-1)+5=14(−3)+5+5+(−2)+5+(−1)+5=14。規定兩個基因的相似度為所有對應方法中,相似度最大的那個。
輸入輸出格式
輸入格式:
共兩行。每行首先是一個整數,表示基因的長度;隔一個空格後是一個基因序列,序列中只含A,C,G,TA,C,G,T四個字母。1 \le1≤序列的長度\le 100≤100。
輸出格式:
僅一行,即輸入基因的相似度。
輸入輸出樣例
輸入樣例#1: 復制7 AGTGATG 5 GTTAG輸出樣例#1: 復制
14
想不出來如何設置狀態 果然還是太垃圾
參考大神的做法:
dp[i][j]
代表的是,第一個堿基序列的第i位對應到第二個堿基的第j位的最大值是多少
這樣 一共有三種狀態轉移方式
接下來就是轉移方程
7 AGTGATG
5 GTTAG
當i=2,j=1時 也就是AG對應G 這個狀態可以由這三個狀態更新
狀態更新也就是,直接匹配、第一個堿基序列加一個空格、第二個堿基序列加一個空格,這三個狀態。
#include<bits/stdc++.h> using namespace std; //input #define rep(i,x,y) for(int i=(x);i<=(y);++i) #define RI(n) scanf("%d",&(n)) #define RII(n,m) scanf("%d%d",&n,&m); #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k) #defineView CodeRS(s) scanf("%s",s) #define LL long long #define REP(i,N) for(int i=0;i<(N);i++) #define CLR(A,v) memset(A,v,sizeof A) ////////////////////////////////// #define N 150 #define inf 0x3f3f3f3f int dp[N][N]; int la,lb,a[N],b[N]; int v[6][6]={ {0,0,0,0,0,0}, {0,5,-1,-2,-1,-3}, {0,-1,5,-3,-2,-4}, {0,-2,-3,5,-2,-2}, {0,-1,-2,-2,5,-1}, {0,-3,-4,-2,-1,0} }; int main() { rep(i,1,N)rep(j,1,N)dp[i][j]=-inf; cin>>la; for(int i=1;i<=la;i++) { char x; cin>>x; if(x==‘A‘) a[i]=1; if(x==‘C‘) a[i]=2; if(x==‘G‘) a[i]=3; if(x==‘T‘) a[i]=4; } cin>>lb; for(int i=1;i<=lb;i++) { char x; cin>>x; if(x==‘A‘) b[i]=1; if(x==‘C‘) b[i]=2; if(x==‘G‘) b[i]=3; if(x==‘T‘) b[i]=4; } for(int i=1;i<=la;i++) dp[i][0]=dp[i-1][0]+v[a[i]][5]; for(int i=1;i<=lb;i++) dp[0][i]=dp[0][i-1]+v[5][b[i]]; for(int i=1;i<=la;i++) { for(int j=1;j<=lb;j++) { dp[i][j]=max(dp[i][j],dp[i-1][j]+v[a[i]][5]);//第一個堿基序列加空格 dp[i][j]=max(dp[i][j],dp[i][j-1]+v[5][b[j]]);//第二個堿基序列加空格 dp[i][j]=max(dp[i][j],dp[i-1][j-1]+v[a[i]][b[j]]);//直接匹配 } } cout<<dp[la][lb]; return 0; }
P1140 相似基因 DP