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 }
花匠-找拐点

 

posted @ 2016-07-12 20:48  阿波罗2003  阅读(...)  评论(...编辑  收藏