zoukankan      html  css  js  c++  java
  • noip 2013 提高组 Day2 部分题解

    积木大赛:

      之前没有仔细地想,然后就直接暴力一点(骗点分),去扫每一高度,连到一起的个数,于是2组超时

    先把暴力程序贴上来(可以当对拍机)

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 FILE *fin = fopen("block.in","r");
     5 FILE *fout= fopen("block.out","w");
     6 int *h;
     7 int n;
     8 int maxHeight = -1;
     9 long long times = 0;
    10 int main(){
    11     fscanf(fin,"%d",&n);
    12     h = new int[(const int)(n + 1)];
    13     for(int i = 1;i <= n;i++){
    14         fscanf(fin,"%d",&h[i]);
    15         if(h[i] > maxHeight) maxHeight = h[i];
    16     }
    17     char isNew = 0x00;
    18     for(int i = 1;i <= maxHeight;i++){
    19         isNew = 0x00;
    20         for(int j = 1;j <= n;j++){
    21             if(h[j] >= i && isNew == 0){
    22                 times++;
    23                 isNew = 0x01;
    24             }
    25             if(h[j] < i && isNew== 0x01){
    26                 isNew = 0x00;
    27             }
    28         }    
    29     }
    30     fprintf(fout,"%ld",times);
    31 }

      然而用样例来举个例子

           *
          *    *
     *    *    *         *
     *    *    *    *    *
    -----------------------------
     1    2    3    4    5

      当第i列的目标高度比第(i-1)高的时候,很容易发现,需要多耗费(h[i]-h[i - 1])次操作,因为在操作使第(i-1)列达到目标高度时,第i列和目标高度还差

    (h[i]-h[i - 1]),每次只能放一层的积木,所以需要多耗费(h[i]-h[i - 1])次操作。

      例如把第一层放满,其它层还需要的高度

     
               
               *         
          *    *         *
    -----------------------------
     1    2    3    4    5

       这样会很奇怪,为什么第5列还需要放一次呢?那是因为第一次方的区间是[1,5],每次求差相当于把这一块连续的这一块放上积木

    从图中可以看出如果h[i] <= h[i - 1]则不用处理,于是我们可以得到如下递推式

           |- f[i - 1] ( h[i] <= h[i - 1] )
     f[i]=|
           |- f[i - 1] + ( h[i]-h[i - 1] ) ( h[i] > h[i - 1] )

    最后,附上代码,说明长,代码不长:

     1 #include<iostream>
     2 #include<fstream>
     3 using namespace std;
     4 ifstream fin("block.in");
     5 ofstream fout("block.out");
     6 int buffer[2];
     7 int n;
     8 long long result = 0;
     9 int main(){
    10     fin>>n;
    11     for(int i = 1;i <= n;i++){
    12         fin>>buffer[1];
    13         if( buffer[1] > buffer[0] ) result += buffer[1] - buffer[0];
    14         buffer[0] = buffer[1];
    15     }
    16     fout<<result;
    17     return 0;
    18 }
    积木大赛

    花匠:

      这道题最开始用的是DP,虽然没有优化且明知复杂度是O(N2)但还是用它去骗骗分

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 FILE *fin = fopen("flower.in","r");
     5 FILE *fout= fopen("flower.out","w");
     6 int *f;
     7 int *f1;
     8 int *h;
     9 int n;
    10 int main(){
    11     fscanf(fin,"%d",&n);
    12     f = new int[(const int)(n + 1)];
    13     f1 = new int[(const int)(n + 1)];
    14     h = new int[(const int)(n + 1)];
    15     for(int i = 1;i <= n;i++){
    16         fscanf(fin,"%d",&h[i]);
    17         f[i] = 1;
    18         f1[i] = 1;
    19     }
    20     for(int i = 2;i <= n; i++){
    21         for(int j = i-1;j > 0;j--){
    22             if(f[j]%2 == 1&&h[i]>h[j]){
    23                 f[i] = max( f[j] + 1,f[i]);
    24             }
    25             if(f1[j]%2 == 1&&h[i]<h[j]){
    26                 f1[i] = max(f1[j] + 1,f1[i]);
    27             }
    28             if(f[j]%2 == 0&&h[i]<h[j]){
    29                 f[i] = max(f[j] + 1,f[i]);
    30             }
    31             if(f1[j]%2 == 0&&h[i]>h[j]){
    32                 f1[i] = max(f1[j] + 1,f1[i]);
    33             }
    34         }
    35     }
    36     int maxv = -1;
    37     for(int i = 1;i <= n;i++){
    38         maxv = max(f[i],maxv);
    39         maxv = max(f1[i],maxv);
    40     }
    41     fprintf(fout,"%ld",maxv);
    42     return 0;
    43 }

      至于最简单、快捷的方法就是找拐点,一个拐点就是一个答案,至于依据嘛,画画图就能理解了

     1 #include<iostream>
     2 #include<fstream>
     3 #include<cstring>
     4 using namespace std;
     5 ifstream fin("flower.in");
     6 ofstream fout("flower.out");
     7 int n;
     8 int *h;
     9 int result = 1;
    10 void init(){
    11     fin>>n;
    12     h = new int[(const int)(n + 1)];
    13     memset(h, 0,sizeof(int)*(n + 1));
    14     for(int i = 1;i <= n;i++){
    15         fin>>h[i];
    16     }
    17 }
    18 char aFlag = -1;
    19 int main(){
    20     init();
    21     for(int i = 1;i < n; i++){
    22         if(h[i] > h[i + 1] && (aFlag == 0 || aFlag == -1) ){
    23             result++;
    24             aFlag = 1;
    25         }
    26         if(h[i] < h[i + 1] && (aFlag == 1 || aFlag == -1) ){
    27             result++;
    28             aFlag = 0;
    29         }
    30     }
    31     fout<<result;
    32     return 0;
    33 }
    花匠-找拐点
  • 相关阅读:
    逆变电路技术研究!
    GOOGLE日历(管理自己的日常事务!)
    MATLAB使用的几个小问题(随笔记录下,用作以后参考!)
    ASP.NET截取字符串
    ASP.NET以及JS获取URL和IP地址
    Jvascript 做IE功能按钮,打开、另存为。属性、打印、收藏夹等js按钮
    C# winform 动态添加控件 以及 事件
    VS2008简体中文正式版序列号
    js 获取日期
    ASP.NET读取XML某节点所有数据返回DataTable实例
  • 原文地址:https://www.cnblogs.com/yyf0309/p/5664820.html
Copyright © 2011-2022 走看看