题目大意:给你一个序列,你可以翻转任意一段子序列一次,求最长不下降子序列长度
tips:子序列可以不连续,但不能破坏在原序列中的顺序
观察数据范围,n<=50,很小,考虑dfs
*dfs来跑区间dp可以巧妙的解决区间两端元素的置换问题
记忆化搜索,f[i][j][l][r] 代表对于区间[i,j],构成最长不下降子序列的元素值域在[l,r]时,最长不下降子序列的长度
注意特判端点
1 #include <bits/stdc++.h> 2 #define N 55 3 #define inf 0x3f3f3f3f 4 using namespace std; 5 6 int n,m; 7 int a[N],f[N][N][N][N]; 8 int dfs(int i,int j,int l,int r) 9 { 10 int ans=-1; 11 if(f[i][j][l][r]!=-1) {return f[i][j][l][r];} 12 if(l>r) {return -1;} 13 if(i>j) {return 0;} 14 if(i==j&&l<=a[i]&&a[i]<=r) {f[i][j][l][r]=1;return 1;} 15 if(i==j&&(a[i]<l||a[i]>r)) {f[i][j][l][r]=0;return 0;} 16 ans=max(ans,dfs(i+1,j,l,r)); 17 ans=max(ans,dfs(i,j-1,l,r)); 18 ans=max(ans,dfs(i+1,j-1,l,r)); 19 if(l<=a[i]&&a[i]<=r) {ans=max(ans,dfs(i+1,j,a[i],r)+1);} 20 if(l<=a[j]&&a[j]<=r) {ans=max(ans,dfs(i,j-1,l,a[j])+1);} 21 if(l<=a[i]&&a[i]<=a[j]&&a[j]<=r) {ans=max(ans,dfs(i+1,j-1,a[i],a[j])+2);} 22 23 if(l<=a[j]) {ans=max(ans,dfs(i+1,j-1,a[j],r)+1);} 24 if(a[i]<=r) {ans=max(ans,dfs(i+1,j-1,l,a[i])+1);} 25 if(r>=a[i]&&a[i]>=a[j]&&a[j]>=l) {ans=max(ans,dfs(i+1,j-1,a[j],a[i])+2);} 26 f[i][j][l][r]=max(0,ans); 27 return ans; 28 } 29 30 int main() 31 { 32 scanf("%d",&n); 33 for(int i=1;i<=n;i++) 34 {scanf("%d",&a[i]);} 35 memset(f,-1,sizeof(f)); 36 printf("%d",dfs(1,n,1,50)); 37 return 0; 38 }