动态规划:LIS

题目中的严格二字,表示的意思是不允许≥或者是≤的情况出现,只允许>的情况以及<的情况

经典问题是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 }
原文地址:https://www.cnblogs.com/aininot260/p/9305962.html