zoukankan      html  css  js  c++  java
  • 算法提高--最长上升子序列一

    https://www.acwing.com/problem/content/897/

     

     1 #include <iostream>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 const int N=1010;
     6 int w[N],f[N];
     7 int main()
     8 {
     9     int n;
    10     cin>>n;
    11     for(int i=1;i<=n;i++) cin>>w[i];
    12     for(int i=1;i<=n;i++){
    13         f[i]=1;
    14         for(int j=1;j<i;j++){
    15             if(w[i]>w[j])
    16                 f[i]=max(f[i],f[j]+1);
    17         }
    18     }
    19     int res=-1;
    20     for(int i=1;i<=n;i++) res=max(res,f[i]);
    21     cout<<res;
    22     return 0;
    23 }

    https://www.acwing.com/problem/content/1019/

    扩展1:最长上升子序列扩展为双向,从左到右或者从右到左。

    在反着做一遍最长上升子序列即可。

     1 #include <iostream>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 const int N=110;
     6 int w[N],f[N],g[N];//f[i]表示1~i且包含i的最长上升子序列的长度。
     7                     //g[i]表示n-1~i且包含i的最长上升子序列的长度。
     8 int main()
     9 {
    10     int T;
    11     cin>>T;
    12     while(T--){
    13         int n;
    14         cin>>n;
    15         for(int i=0;i<n;i++) cin>>w[i];
    16         int res=0;
    17         for(int i=0;i<n;i++){
    18             f[i]=1;
    19             for(int j=0;j<i;j++){
    20                 if(w[i]>w[j])
    21                     f[i]=max(f[i],f[j]+1);
    22             }
    23             res=max(res,f[i]);
    24         }
    25         for(int i=n-1;i>=0;i--){
    26             g[i]=1;
    27             for(int j=n-1;j>i;j--){
    28                 if(w[i]>w[j])
    29                     g[i]=max(g[i],g[j]+1);
    30             }
    31             res=max(res,g[i]);
    32         }
    33         cout<<res<<endl;
    34     }
    35     return 0;
    36 }

    https://www.acwing.com/problem/content/1016/

    1、按顺序浏览景点

    2、任意两相邻景点高度不同

    3、一旦开始下山就不能在往上

    也即要找到一个子序列使得高度呈现以上的形态。

    类比上一怪盗基德的题,我们可以枚举最高点。

    最高点作为左边和右边上升子序列的最高点。

    求出以这个点 i 结尾的从左开始的最长上升子序列和从右开始的最长上升子序列,遍历一遍即可。

    【注】最高点加了两遍,所以要减一

     1 #include <iostream>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 const int N=1010;
     6 int w[N],f[N],g[N];//f[i]表示1~i且包含i的最长上升子序列的长度。
     7                     //g[i]表示n-1~i且包含i的最长上升子序列的长度。
     8 int main()
     9 {
    10     int n;
    11     cin>>n;
    12     for(int i=0;i<n;i++) cin>>w[i];
    13     for(int i=0;i<n;i++){
    14         f[i]=1;
    15         for(int j=0;j<i;j++){
    16             if(w[i]>w[j])
    17                 f[i]=max(f[i],f[j]+1);
    18         }
    19     }
    20     for(int i=n-1;i>=0;i--){
    21         g[i]=1;
    22         for(int j=n-1;j>i;j--){
    23             if(w[i]>w[j])
    24                 g[i]=max(g[i],g[j]+1);
    25         }
    26     }
    27     int res=0;
    28     for(int i=0;i<n;i++) res=max(res,f[i]+g[i]-1);
    29     cout<<res<<endl;
    30     return 0;
    31 }

    https://www.acwing.com/problem/content/484/

    2004 NOIP提高组 合唱队形

    问题同登山,不过问的是最少出列几个同学能够使得队形成为上升再下降的形状。

    出来的最少==留下的最多。

    cout<<n-res即可。

    https://www.acwing.com/problem/content/1014/

     1 #include <iostream>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 typedef pair<int,int> PII;
     6 const int N=5010;
     7 PII w[N];
     8 int f[N];
     9 int main()
    10 {
    11     int n;
    12     cin>>n;
    13     for(int i=0;i<n;i++) cin>>w[i].first>>w[i].second;
    14     sort(w,w+n);
    15     int res=0;
    16     for(int i=0;i<n;i++){
    17         f[i]=1;
    18         for(int j=0;j<i;j++){
    19             if(w[i].second>w[j].second)
    20                 f[i]=max(f[i],f[j]+1);
    21         }
    22         res=max(res,f[i]);
    23     }
    24     cout<<res;
    25     return 0;
    26 }

    https://www.acwing.com/problem/content/1018/

     

     1 #include <iostream>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 const int N=1010;
     6 int w[N],f[N];
     7 int main()
     8 {
     9     int n;
    10     cin>>n;
    11     for(int i=0;i<n;i++) cin>>w[i];
    12     int res=0;
    13     for(int i=0;i<n;i++){
    14         f[i]=w[i];
    15         for(int j=0;j<i;j++){
    16             if(w[i]>w[j])
    17                 f[i]=max(f[i],f[j]+w[i]);
    18         }
    19         res=max(res,f[i]);
    20     }
    21     cout<<res;
    22     return 0;
    23 }
  • 相关阅读:
    deb包的2种安装安装方法
    苹果全系产品信息查询
    水货的运作流程
    关于手机字库损坏的真相
    关闭IOS更新功能(ios4/5/6)
    c++ builder xe2 字符串转日期
    《windows核心编程》 18章 堆
    《windows核心编程》 17章 内存映射文件
    使用内存映射文件来共享数据
    <转>C++位运算详解
  • 原文地址:https://www.cnblogs.com/greenofyu/p/14961460.html
Copyright © 2011-2022 走看看