zoukankan      html  css  js  c++  java
  • [NOIP2013 花匠] 新人解题报告

           本来按照老师的要求,我学OI的第一份解题报告应是在寒假完成的关于数据结构的基础题,但由于身体原因当时未能完成,那么就在省选赛前临时写几篇吧……
    题目描述

    花匠栋栋种了一排花,每株花都有自己的高度。花儿越长越大,也越来越挤。栋栋决定把这排中的一部分花移走,将剩下的留在原地,使得剩下的花能有空间长大,同时,栋栋希望剩下的花排列得比较别致。

    具体而言,栋栋的花的高度可以看成一列整数ℎ1, ℎ2, … , ℎn。设当一部分花被移走后,剩下的花的高度依次为g1, g2, … , gm,则栋栋希望下面两个条件中至少有一个满足:

    条件 A:对于所有的1 ≤ i ≤ m/2,g2i > g2i−1,且g2i > g2i+1

    条件 B:对于所有的1 ≤ i ≤ m/2,g2i < g2i−1,且g2i < g2i+1

    注意上面两个条件在m = 1时同时满足,当m > 1时最多有一个能满足。

    请问,栋栋最多能将多少株花留在原地。

    输入
    输入的第一行包含一个整数 ,表示开始时花的株数。
    第二行包含 个整数,依次为ℎ1, ℎ2,… , ℎn,表示每株花的高度。
    输出
    输出一行,包含一个整数m,表示最多能留在原地的花的株数
    样例
    FlowerNOIP2013.in
    5
    5 3 2 1 2
    FlowerNOIP2013.out
    3
    数据范围
    对于 20%的数据,n ≤ 10;
    对于 30%的数据,n ≤ 25;
    对于 70%的数据,n ≤ 1000,0 ≤ h_i ≤ 1000;
    对于 100%的数据,1 ≤ n ≤ 100,000,0 ≤ h_i ≤1,000,000,所有的h_i随机生成,所有随机数服从某区间内的均匀分布。
     
    个人分析

     明显的最优子结构性质,可以用动规来做。应该注意到存在30%的变态数据(
    1 ≤ n ≤ 100,000,0 ≤ h_i ≤1,000,000),因此想拿满分应当找到线性的算法(这种提示也可以?…………)。A、B两种情况不仅不会增加复杂性,反而消除了对n奇偶性的讨论。两种情况可以简化为一种锯齿状的数列,只需讨论i前保留的花高度与花i的高度h[i]的关系即可。
    第i朵花的高度为h[i](1 <= i <= n),前i朵花“尾部为升序”的最长序列长度为S1[i],“尾部为降序”的最长序列长度为S2[i]。
    则有状态转移方程:

        1. (h[i] > h[i-1]):S1[i] = max(S1[i-1], S2[i-1] + 1);S2[i] = S2[i-1];
        2. (h[i] == h[i-1]):S1[i] = S1[i-1];S2[i] = S2[i-1];
        3. (h[i] < h[i-1]):S1[i] = S1[i-1];S2[i] = max(S2[i-1], S1[i-1] + 1);

    由此可以写出复杂度为O(n)的动态规划代码:

     1 //<NOIP2013> 花匠
     2 #include <cstdio>
     3 using namespace std;
     4 int maxm(int a, int b)
     5 {
     6     if(a >= b )return a ;
     7         else return b;
     8 }
     9 const int maxn = 1000005;
    10 int h[maxn] = {0};  //
    11 int n;
    12 int S1[maxn], S2[maxn] ;
    13 //(1尾部为升序,2尾部为降序)
    14 int main(void)
    15 {
    16     FILE *in = fopen ("FlowerNOIP2013.in","r");
    17     FILE *out = fopen ("FlowerNOIP2013.out" ,"w");
    18     fscanf(in"%d", &n);
    19     int i;
    20     for(i = 1; i <= n; i++)
    21         fscanf(in"%d", &h[i]);
    22     S1[1] = S2[1] = 1;   //初始状态
    23     
    24     for(int i = 2;i <= n; i++)
    25     {
    26         if(h[i] > h[i-1]) // case1
    27         {
    28             S1[i] = maxm(S1[i-1], S2[i-1]+1 );
    29             S2[i] = S2[i-1];
    30         }
    31         else if (h[i] == h[i-1])// case2
    32         {
    33             S1[i] = S1[i-1];
    34             S2[i] = S2[i-1];
    35         }
    36         else    //case 3
    37         {
    38             S1[i] = S1[i-1];
    39             S2[i] = maxm(S1[i-1]+1, S2[i-1] );
    40         }
    41     }
    42     
    43     fprintf(out"%d", maxm(S1[n], S2[n]) );
    44     return 0;
    45 }
  • 相关阅读:
    课堂作业04 2017.10.27
    课程作业 03 动手动脑 2017.10.20
    课程作业 03 2017.10.20
    HDU 3974 Assign the task
    POJ 2155 Matrix
    POJ 2481 Cows
    HDU 3038 How Many Answers Are Wrong
    CS Academy Array Removal
    POJ_1330 Nearest Common Ancestors LCA
    CF Round 427 D. Palindromic characteristics
  • 原文地址:https://www.cnblogs.com/Asm-Definer/p/3761681.html
Copyright © 2011-2022 走看看