AcWing每日一题--合唱队形

1、DP写法

f [ i ] 表示以 i 结尾的子序列的最长长度。

g [ i ] 表示从尾部出发,以 i 结尾的子序列的最长长度。

那么假设选定 i 为最高点的话,合唱队形人数为f [ i ] + g [ i ] - 1 ,减一是因为 i 算了两次。

 1 #include<iostream>
 2 using namespace std;
 3 const int N=110;
 4 int a[N],f[N],g[N];
 5 int main(void){
 6     int n;
 7     cin>>n;
 8     for(int i=1;i<=n;i++){
 9          cin>>a[i];
10     }
11     for(int i=1;i<=n;i++){//正着做一遍最长子序列
12         f[i]=1;
13         for(int j=1;j<i;j++){
14             if(a[i]>a[j]){
15                 f[i]=max(f[i],f[j]+1);
16             }
17         }
18     }
19     
20     for(int i=n;i>=1;i--){//反着做一遍最长子序列
21         g[i]=1;
22         for(int j=n;j>i;j--){
23             if(a[i]>a[j]){
24                 g[i]=max(g[i],g[j]+1);
25             }
26         }
27     }
28     int res=0;
29     for(int i=1;i<=n;i++){//统计答案
30         res=max(res,f[i]+g[i]-1);
31     }
32     cout<<n-res;
33     return 0;
34 }

2、优化写法(贪心)

 1 #include<iostream>
 2 #include<cstring>
 3 using namespace std;
 4 const int N=110;
 5 int a[N],f[N],g[N],d[N];
 6 int main(void){
 7     int n;
 8     cin>>n;
 9     for(int i=1;i<=n;i++){
10         cin>>a[i];
11     }
12 
13     //求f
14     memset(d,0,sizeof(d));
15     d[0]=0;
16     int len=0;
17     for(int i=1;i<=n;i++){
18         int l=0,r=len;
19         while(l<r){
20             int mid=l+r+1>>1;
21             if(d[mid]<a[i]) l=mid;
22             else r=mid-1;
23         }
24         len=max(len,r+1);
25         f[i]=r+1;
26         d[r+1]=a[i];
27     }
28 
29     //求g
30     memset(d,0,sizeof(d));
31     len=0;
32     for(int i=n;i>=1;i--){//必须从后往前,依据题意要求的g是从尾部到i的上升序列的最大长度
33                             //而从前往后算递减的话(假设g[1]最大)g[1]=1,而他应该为n的。
34         int l=0,r=len;
35         while(l<r){
36             int mid=l+r+1>>1;
37             if(d[mid]<a[i]) l=mid;
38             else r=mid-1;
39         }
40         len=max(len,r+1);
41         g[i]=r+1;
42         d[r+1]=a[i];
43     }
44 
45 
46     //统计答案
47     int res=0;
48     for(int i=1;i<=n;i++){
49         res=max(res,f[i]+g[i]-1);
50     }
51     cout<<n-res;
52 
53     return 0;
54 }
原文地址:https://www.cnblogs.com/greenofyu/p/14339875.html