zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    poj 2187 Beauty Contest (凸包)
    poj 1584 A Round Peg in a Ground Hole(计算几何)
    poj 1039 Pipe (计算几何)
    struts2开篇
    Action的内容
    输入校验
    文件上传
    Struts.xml内容
    .NET资源推荐:数据持久层
    线程间操作无效: 从不是创建控件“...”的线程访问它。
  • 原文地址:https://www.cnblogs.com/greenofyu/p/14339875.html
Copyright © 2011-2022 走看看