题意:求最长公共上升子序列的长度。
思路:结合了LCS,LIS两个算法的思想,最初我自己思路是根据:LCS很容易想到定义 dp[i][j] 表示第一格串前i个和第二个串的前j个最长公共上升子序列的长度,
首先根据最长公共子序列思想,如果a[i]=b[j],,就在b[1]到b[j-1]前面选一个dp[i][k],满足b[j]>b[k]&&dp[i][k]是最大的,为什么呢?你想,如果某一个时刻a[i]==b[j],那么显然,我们就应该在0到j-1中,找一个dp值最大的来更新最优解,这和最长上升子序列想法是一样的。如果a[i]!=b[j],dp[i][j]=max(dp[i-1][j],dp[i][j-1]).
代码如下:
缺点是这样写,时间复杂度是n^3.
#include<bits/stdc++.h> using namespace std; int a[700],b[700],dp[700][700]; const int inf=0x7fffffff; int main() { int T,ok=0;cin>>T; while(T--){ a[0]=b[0]=-inf; int n,m;cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; cin>>m; for(int i=1;i<=m;i++) cin>>b[i]; memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(a[i]==b[j]){ if(j==1) dp[i][j]=1; for(int k=1;k<j;k++){//寻找满足条件的最大k if(b[j]>b[k]) dp[i][j]=max(dp[i][j],dp[i][k]+1); } } else{ dp[i][j]=max(dp[i-1][j],dp[i][j-1]); } } } if(!ok) ok=1; else cout<<endl; cout<<dp[n][m]<<endl; } }
上面这个代码,这里当a[i]==b[j],查找最大的k,需要0(n)。但实际上,k并不需要扫一遍,当a[i]!=b[j]的时候就可以保存dp[i][j]中最大的那个一个也就是dp[i][k].解化过的算法时间复杂度是n^2.
zh#include<bits/stdc++.h> using namespace std; int a[700],b[700],dp[700][700]; const int inf=0x7fffffff; int main() { int T,ok=0;cin>>T; while(T--){ a[0]=b[0]=-inf; int n,m;cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; cin>>m; for(int i=1;i<=m;i++) cin>>b[i]; memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++){ int k=1; for(int j=1;j<=m;j++){ if(a[i]==b[j]){ if(j==1) dp[i][j]=1; if(b[j]>b[k]) dp[i][j]=dp[i][k]+1; } else{ dp[i][j]=max(dp[i-1][j],dp[i][j-1]); if(dp[i][j]>dp[i][k]) k=j; } } } if(!ok) ok=1; else cout<<endl; cout<<dp[n][m]<<endl; } }还有一种思路是:节省一维的空间,定义dp[i]为以b中第i个位置结尾的子串和a的最长公共上升子序列的长度,然后看代码吧,思路和上面的差不多.....
#include<bits/stdc++.h> using namespace std; int dp[1100],a[1100],b[1100],k; int main() { int T,ans,ok=0;cin>>T; while(T--){ int n,m; cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; cin>>m; for(int i=1;i<=m;i++) cin>>b[i]; memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++){ k=1; for(int j=1;j<=m;j++){ if(a[i]==b[j]){ dp[j]=max(dp[j],dp[k]+1); } if(a[i]>b[j]){ if(dp[k]<dp[j]) k=j; } } } if(!ok) ok=1; else cout<<endl; ans=0; cout<<*max_element(dp+1,dp+m)<<endl; } }