木板墙问题
考古学家在人迹罕至的一块平地上发现了由一堆木板拼成的墙。
令人惊奇的是这些木板的宽度都相同!地下的部分都已腐烂,而地上的部分也有高有低,
甚至有的地方根本没有木板,所以考古学家决定带走面积最大的长方形回去研究。 输入: 首先是整数n(1<=n<=100000),表示木板的块数。接下来是n个整数h1,...,hn, 其中0<=hi<=1000000000,它们按照从左到右的顺序表示木板的高度。每块木板的宽度都是1。 最后一个0表示程序的结束。 输出: 其中最大长方形的面积。
测试输入
3 2000 2000 2000
7 1 2 5 6 1 3 3
0
测试输出
6000
10
图示如下
思路:最优解的矩形区域的高度是由该矩形区域中所包含的最低的木板决定。我们可以遍历一遍数据,判断出哪一个木板作为基准木板(矩形高度),并分别左右扩展为矩形区域所得到的面积最大,这个面积就是最优解。然后这个问题的关键就变成了如何确定一块木板能向左(右)扩展多少个。
方法如下
以n[i][1]表示第i个木板作为基准木板时能向左扩展的个数。
如果左相邻的木板高度小于基准木板,则该方向能扩展0个。否则 n[i][1]+=n[i-1][1]+1,然后再以第(i-2-n[i-1][1])块木板作为当前基准木板的左相邻木板继续循环的判断,直到某一个相邻的木板高度小于基准木板就结束。
代码如下
#include<stdio.h> long long n[100002][3]; long long max,sum; char c; int main() { while(scanf("%lld",&sum)&&sum) { c=getchar(); max=0; for(int i=1;i<=sum;i++) { scanf("%lld",&n[i][0]); n[i][1]=n[i][2]=0; } for(int i=2;i<=sum;i++) { if(n[i][0]>n[i-1][0]) n[i][1]=0; else { int k=i-1-n[i-1][1]-1; while(k>0&&n[k][0]>=n[i][0]) { k=k-n[k][1]-1; } n[i][1]=i-k-1; } } for(int i=sum-1;i>=1;i--) { if(n[i][0]>n[i+1][0]) n[i][2]=0; else { int k=i+1+n[i+1][2]+1; while(k<=sum&&n[k][0]>=n[i][0]) { k=k+n[k][2]+1; } n[i][2]=k-i-1; } } for(int i=1;i<=sum;i++) { if((n[i][1]+n[i][2]+1)*n[i][0]>max) max=(n[i][1]+n[i][2]+1)*n[i][0]; } printf("%lld\n",max); } return 0; }