bzoj 4275 Badania naukowe —— DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4275
枚举 \( C \) 在 \( A \) 和 \( B \) 中的位置,然后取它前后的最长子序列;
\( n^2 \) DP即可,呵呵。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int const xn=3005; int n,m,l,a[xn],b[xn],c[xn],f[xn][xn],g[xn][xn],pa[xn],pb[xn]; int rd() { int ret=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();} while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar(); return f?ret:-ret; } int main() { n=rd(); for(int i=1;i<=n;i++)a[i]=rd(); m=rd(); for(int i=1;i<=m;i++)b[i]=rd(); l=rd(); for(int i=1;i<=l;i++)c[i]=rd(); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { f[i][j]=max(f[i-1][j],f[i][j-1]); if(a[i]==b[j])f[i][j]=max(f[i][j],f[i-1][j-1]+1); } if(l==0){printf("%d\n",f[n][m]); return 0;}// for(int i=n;i;i--) for(int j=m;j;j--) { g[i][j]=max(g[i+1][j],g[i][j+1]); if(a[i]==b[j])g[i][j]=max(g[i][j],g[i+1][j+1]+1); } memset(pa,-1,sizeof pa); for(int i=1;i<=n;i++) for(int j=i,k=l;j;j--) { if(a[j]==c[k])k--; if(k==0){pa[i]=j; break;} } memset(pb,-1,sizeof pb); for(int i=1;i<=m;i++) for(int j=i,k=l;j;j--) { if(b[j]==c[k])k--; if(k==0){pb[i]=j; break;} } int ans=-1; for(int i=1;i<=n;i++) if(pa[i]!=-1) for(int j=1;j<=m;j++) if(pb[j]!=-1)ans=max(ans,f[pa[i]-1][pb[j]-1]+g[i+1][j+1]); if(ans==-1)puts("-1");// else printf("%d\n",ans+l); return 0; }