删除最少的元素(最长不上升子序列系列)
给定有n个数的A序列:A1,A2,A3⋯An。
对于这个序列,我们想得到一个子序列Ap1,Ap2,Ap3⋯Api⋯Apm(1<=p1<p2<p3…<pi…<pm<=n),满足Ap1>=Ap2>=Ap3>=⋯>=Api<=⋯<=Apm。
从A序列最少删除多少元素,可以得到我们想要的子序列。
输入格式
第一行输入一个整数n,代表A序列中数字的个数。
第二个输入n个整数,代表A1,A2,A3⋯An。(1≤n≤1000,1≤Ai≤10000)
输出格式
输出需要删除的元素个数,占一行。
样例输入
7 3 2 4 1 2 5 3
样例输出
2
解题思路
可以从前往后做一次最长不升子序列,在从后往前做最长不上升子序列。
分别记录从前往后以第i个元素为结尾的最长不升子序列长度dp1[i],和从后往前以第i个元素为结尾的最长不升子序列长度dp2[i]。
这样dp1[i]+dp2[i]-1就是得到的B序列的长度。
故考虑枚举每一个点作为中间的转折点,那保留的最长的子序列也就是以这个点为终点的最长不上升子序列和以这个点为起点的最长上升子序列的和减1,那么就正反做两遍最长不上升子序列,然后遍历每个点统计最优答案。
1 #include <stdio.h> 2 #include <string.h> 3 #include <iostream> 4 #include <string> 5 #include <math.h> 6 #include <algorithm> 7 #include <vector> 8 #include <stack> 9 #include <queue> 10 #include <set> 11 #include <map> 12 #include <sstream> 13 const int INF=0x3f3f3f3f; 14 typedef long long LL; 15 const int maxn=1e5+10; 16 using namespace std; 17 18 int a[1010]; 19 int dp[1010];//从1到i的最长不上升子序列 20 int rdp[1010];//从n到i的最长不上升子序列,即从i到n的最长不下降子序列 21 22 int main() 23 { 24 int n; 25 scanf("%d",&n); 26 int ans=INF; 27 for(int i=1;i<=n;i++) 28 { 29 scanf("%d",&a[i]); 30 dp[i]=1; rdp[i]=1; 31 } 32 for(int i=1;i<=n;i++) 33 { 34 for(int j=1;j<i;j++) 35 { 36 if(a[j]>=a[i]) 37 dp[i]=max(dp[i],dp[j]+1); 38 } 39 } 40 for(int i=n;i>=1;i--) 41 { 42 for(int j=n;j>i;j--) 43 { 44 if(a[j]>=a[i]) 45 rdp[i]=max(rdp[i],rdp[j]+1); 46 } 47 } 48 for(int i=1;i<=n;i++) 49 ans=min(ans,n-(dp[i]+rdp[i]-1)); 50 printf("%d\n",ans); 51 return 0; 52 }
-