积木大赛:
之前没有仔细地想,然后就直接暴力一点(骗点分),去扫每一高度,连到一起的个数,于是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] )
最后,附上代码,说明长,代码不长:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 }
至于最简单、快捷的方法就是找拐点,一个拐点就是一个答案,至于依据嘛,画画图就能理解了
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 }