密碼脫落-藍橋杯-最大公共子序列
阿新 • • 發佈:2022-02-10
https://www.acwing.com/problem/content/description/1224/
最長公共子序列問題在《演算法導論》P222頁有其原理證明。
“比對兩段DNA序列的相似度”就是一個很好的例子。
動態規劃的核心思想就是自底向上地解決遞迴中的重複子結構問題。利用空間迭代(或者說是狀態轉移)來換取遞迴的堆疊操作和時間。
純dfs解法1:33分,但其實應該是錯的,最小解應該取兩個dfs的min
#include<bits/stdc++.h> using namespace std; string s; int ans; void dfs(int i,int j,int u){ if(i>=j) { ans=u; return ; } if(s[i]!=s[j]){ dfs(i+1,j,u+1); dfs(i,j-1,u+1); }else{ dfs(i+1,j-1,u); } return ; } int main(){ cin>>s; int n=s.size(); dfs(0,n-1,0); cout<<ans; return 0; }
純dfs解法2:正確寫法:
此題無法繼續剪枝;
#include<stdc++.h> using namespace std; string s; int ans; int dfs(int i,int j,int u){ if(i>=j) { return u; } if(s[i]!=s[j]){ return min(dfs(i+1,j,u+1),dfs(i,j-1,u+1)); }else{ return dfs(i+1,j-1,u); } } int main(){ cin>>s; int n=s.size(); cout<<dfs(0,n-1,0); return 0; }
3.dp區間規劃:
為了方便理解我還是單獨開闢空間給逆序串來比對
優雅而快捷~
#include<bits/stdc++.h> using namespace std; const int N=1010; string s; int dp[N][N]; int main(){ cin>>s; int n=s.size(); string s2=s; reverse(s2.begin(),s2.end()); //單獨開闢空間給逆序串來比對 for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(s[i]==s2[j]) dp[i][j]=dp[i-1][j-1]+1; else dp[i][j]=max(dp[i-1][j],dp[i][j-1]); } } cout<<n-dp[n][n]; return 0; }