zoukankan      html  css  js  c++  java
  • 花匠

    【题目描述】

    花匠栋栋种了一排花,每株花都有自己的高度。花儿越长越大,也越来越挤。栋栋决定把这排中的一部分花移走,将剩下的留在原地,使得剩下的花能有空间长大,同时,栋栋希望剩下的花排列得比较别致。
    具体而言,栋栋的花的高度可以看成一列整数H1,H2,…,Hn。设当一部分花被移走后,剩下的花的高度依次为G1,G2,…,Gm,则栋栋希望下面两个条件中至少有一个满足:
    条件A:对于所有的1< i <m/2,G2*i > G2*i-1,且G2*i > G2*i+1; 
    条件B:对于所有的1< i <m/2,G2*i < G2*i-1,且G2*i < G2*i+1。
    注意上面两个条件在m = 1时同时满足,当m > 1时最多有一个能满足。
    请问,栋栋最多能将多少株花留在原地。

    【输入描述】

    输入的第一行包含一个整数n,表示开始时花的株数。
    第二行包含n个整数,依次为H1,H2,…,Hn,表示每株花的高度。

    【输出描述】

    输出一行,包含一个整数m,表示最多能留在原地的花的株数。

    【样例输入】


    5 3 2 1 2

    【样例输出】

    3

    【数据范围及提示】

    对于 20%的数据,n ≤ 10; 
    对于 30%的数据,n ≤ 25; 
    对于 70%的数据,n ≤ 1000,0 ≤ Hi ≤ 1000; 
    对于 100%的数据,1 ≤ n ≤ 100,000,0 ≤ Hi ≤ 1,000,000。

    解法一:

    抖动序列DP:O(n^2)

    源代码:
    
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int n,i[100001],f[100001][2]={0}; //f[i][0]代表小大小,f[i][1]代表大小大。
    int main() //自惭形秽的O(n^2)DP。
    {
        scanf("%d",&n);
        for (int a=1;a<=n;a++)
          scanf("%d",&i[a]);
        f[1][1]=f[1][0]=1; //边界。
        for (int a=2;a<=n;a++)
        {
            int t1(0),t2(0); //t1代表降序到达i[b]的最大值,t2代表升序到达i[b]的最小值。
              for (int b=1;b<a;b++) //取最大值。
              {
                  if (f[b][0]>t1&&i[b]>i[a])
                      t1=f[b][0];
                  if (f[b][1]>t2&&i[b]<i[a])
                    t2=f[b][1];
              }
              f[a][1]+=t1+1; //升序到达了i[a]。
              f[a][0]+=t2+1; //降序到达了i[a]。
        }
        printf("%d",max(f[n][0],f[n][1])); //输出最大值。
        return 0;
    }

    优化后:O(n)

    源代码:
    
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int n,i[100001],f[100001][2]={0};
    int main() //转换思想的O(n)DP。
    {
        scanf("%d",&n);
        for (int a=1;a<=n;a++)
          scanf("%d",&i[a]);
        f[1][0]=f[1][1]=1; //边界。
        for (int a=2;a<=n;a++) //依次传值,f[i][0]表示前i株花降序到达的最大值,f[i][1]为与此同类。
        {
            if (i[a]<i[a-1]) //可降序到达。
            {
                f[a][0]=max(f[a-1][1]+1,f[a-1][0]); //选不选此株花。
                f[a][1]=f[a-1][1];
            }
            if (i[a]==i[a-1]) //纯传值。
            {
                f[a][0]=f[a-1][0];
                f[a][1]=f[a-1][1];
            }
            if (i[a]>i[a-1]) //可升序到达。
            {
                f[a][1]=max(f[a-1][0]+1,f[a-1][1]);
                f[a][0]=f[a-1][0];
            }
        }
        printf("%d",max(f[n][0],f[n][1])); //输出最大值。
        return 0;
    }

    解法二:

    模拟解决:

    源代码:
    
    #include<cstdio>
    int n,ans=2,i[100001]; //ans一开始便包括了始点和终点。
    bool s;
    int main()
    {
        scanf("%d",&n);
        for (int a=1;a<=n;a++)
          scanf("%d",&i[a]);
        s=i[1]>i[2]; //模拟的思想为:可以将题意转化为求转折点的最多个数,再通过判断升降序列即可求解。
        for (int a=3;a<=n;a++)
        {
            if (s&&i[a]>i[a-1]) //降序转折。
            {
                ans++;
                s=0;
            }
            if (!s&&i[a]<i[a-1]) //升序转折。
            {
                ans++;
                s=1;
            }
        }
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    论文讨论&&思考《Deformable Convolutional Networks》
    论文笔记《Spatial Memory for Context Reasoning in Object Detection》
    从零开始学习MXnet(四)计算图和粗细粒度以及自动求导
    从零开始学习MXnet(三)之Model和Module
    从零开始学习MXnet(二)之dataiter
    谈一谈深度学习之semantic Segmentation
    从零开始学习MXnet(一)
    机器学习技法笔记(1)
    iOS安装CocoaPods详细过程
    汇编(一)
  • 原文地址:https://www.cnblogs.com/Ackermann/p/5558073.html
Copyright © 2011-2022 走看看