积木大赛:

  之前没有仔细地想,然后就直接暴力一点(骗点分),去扫每一高度,连到一起的个数,于是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 }
积木大赛

相关文章: