reverse一个子序列就是从两端开始swap
然后我们就可以转移了
关键的状态设计是
fi,j,l,r
表示 区间
[i,j]
左边的数是
l
右边的数是
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
using namespace std;
#define read(x) scanf("%d",&(x))
const int N=55;
int n,a[N];
int f[N][N][N][N];
inline int dp(int i,int j,int l,int r){
if (f[i][j][l][r]!=-1) return f[i][j][l][r];
if (l>r) return -1<<29;
if (i>j) return 0;
if (i==j) return l<=a[i] && a[i]<=r;
int ret=0;
ret=max(ret,dp(i+1,j,l,r));
ret=max(ret,dp(i,j-1,l,r));
if (a[j]>=l) ret=max(ret,dp(i+1,j-1,a[j],r)+1);
if (a[i]<=r) ret=max(ret,dp(i+1,j-1,l,a[i])+1);
if (l<=a[j] && a[j]<=a[i] && a[i]<=r) ret=max(ret,dp(i+1,j-1,a[j],a[i])+2);
if (a[i]>=l) ret=max(ret,dp(i+1,j,a[i],r)+1);
if (a[j]<=r) ret=max(ret,dp(i,j-1,l,a[j])+1);
if (l<=a[i] && a[i]<=a[j] && a[j]<=r) ret=max(ret,dp(i+1,j-1,a[i],a[j])+2);
return f[i][j][l][r]=ret;
}
int main(){
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(n);
for (int i=1;i<=n;i++) read(a[i]);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
memset(f,-1,sizeof(f));
printf("%d\n",dp(1,n,0,50));
return 0;
}