题目描述
最长公共上升子序列
f[i][j]代表前i个a和前j个b中,且以bj结尾的最大公共上升子序列
#include <iostream>
using namespace std;
const int N=3010;
int a[N],b[N];
int f[N][N];
int main()
{
cin.tie();
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int i=1;i<=n;i++)
{
cin>>b[i];
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
f[i][j]=f[i-1][j];
if(a[i]==b[j])
{
f[i][j]=max(f[i][j],1);
for(int k=1;k<j;k++)
{
if(b[k]<b[j])
{
f[i][j]=max(f[i][j],f[i][k]+1);
}
}
}
}
}
int res=0;
for(int i=1;i<=n;i++)
{
res=max(res,f[n][i]);
}
cout<<res;
return 0;
}
改进版:
#include <iostream>
using namespace std;
const int N=3010;
int a[N],b[N];
int f[N][N];
int main()
{
cin.tie();
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int i=1;i<=n;i++)
{
cin>>b[i];
}
for(int i=1;i<=n;i++)
{
int maxv=1;
for(int j=1;j<=n;j++)
{
f[i][j]=f[i-1][j];
if(a[i]==b[j])
{
f[i][j]=max(f[i][j],maxv);
}
if(b[j]<a[i])
{
maxv=max(maxv,f[i][j]+1);
}
}
}
int res=0;
for(int i=1;i<=n;i++)
{
res=max(res,f[n][i]);
}
cout<<res;
return 0;
}
2023/11/26
fij代表:由第一个序列前i个字母,第二个序列前j个字母,且以bj结尾的上升子序列
朴素版,三重循环
``
include [HTML_REMOVED]
using namespace std;
const int N=3010;
int f[N][N];
int a[N], b[N];
int n;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int i=1;i<=n;i++)
{
cin>>b[i];
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
// 不选a[i]
f[i][j] = f[i-1][j];
// 选a[i],前提是a[i]要等于b[j]
if(a[i] == b[j])
{
f[i][j] = max(f[i][j], 1);
for(int k=1;k<=j;k++)
{
if(b[j] > b[k])
{
f[i][j] = max(f[i][j], f[i][k] + 1);
}
}
}
}
}
int res = 0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
res= max(res, f[i][j]);
}
}
cout<<res;
return 0;
}
``
优化版:
减少一重循环
for(int i=1;i<=n;i++)
{
int maxv=1;
for(int j=1;j<=n;j++)
{
f[i][j]=f[i-1][j];
if(a[i]==b[j])
{
f[i][j]=max(f[i][j],maxv);
}
if(b[j]<a[i])
{
maxv=max(maxv,f[i][j]+1);
}
}
}