题目中的严格二字,表示的意思是不允许≥或者是≤的情况出现,只允许>的情况以及<的情况
经典问题是NOIP合唱队形,在这个题目中,既求了最长上升子序列,也求了最长下降子序列
其最终的结果由两个子序列的结果共同得来
我们给出实现方法:
//最长上升子序列
for(int i=1;i<=n;i++)
for(int j=i-1;j>=0;j--)
if(a[j]<a[i])
f1[i]=max(f1[i],f1[j]+1);
//最长下降子序列
for(int i=n;i>=1;i--)
for(int j=i+1;j<=n+1;j++)
if(a[j]<a[i])
f2[i]=max(f2[i],f2[j]+1);
以最长上升子序列为例,其转移方程为:f(i)=max(f(i),f(j)+1),并且当a[i]>a[j]时进行转移
在实现的时候,一定要控制好下标,以及边界处理,以上代码的边界处理是没有问题的
下面给出合唱队形这道题的代码:
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int maxn=105; 5 int n; 6 int ans; 7 int a[maxn]; 8 int f1[maxn],f2[maxn]; 9 int main() 10 { 11 scanf("%d",&n); 12 for(int i=1;i<=n;i++) 13 scanf("%d",&a[i]); 14 for(int i=1;i<=n;i++) 15 for(int j=i-1;j>=0;j--) 16 if(a[j]<a[i]) 17 f1[i]=max(f1[i],f1[j]+1); 18 for(int i=n;i>=1;i--) 19 for(int j=i+1;j<=n+1;j++) 20 if(a[j]<a[i]) 21 f2[i]=max(f2[i],f2[j]+1); 22 for(int i=1;i<=n;i++) 23 ans=max(ans,f1[i]+f2[i]); 24 ans=n-ans+1; 25 printf("%d ",ans); 26 return 0; 27 }