【题目大意】
给出n(n<=100000)个木板的高度,宽度均为1,将n个木板竖成一排,在上面截取长方形,求最大面积。
【解题思路】
对于每一块木板,Area=height[i]*(j-k+1) 设其中任一块x, j<=x<=k, height[x]>=height[i]; 找j,k成为关键。
一般方法肯定超时,
- FOR i:=1 TO n
- FOR j:=1 TO n
- k:=Min height[i TO j] ;
- area:=height[k]*(j-i+1);
- END FOR
- END FOR
- return Max area;
利用动态规划,如果它左边高度大于等于它本身,那么它左边的左边界一定满足这个性质,再从这个边界的左边迭代下去
- for(i=1;i<=n;i++) {
- while(a[l[i]-1]>=a[i])
- l[i]=l[l[i]-1];
- }
- for(i=n;i>=1;i–) {
- while(a[r[i]+1]>=a[i])
- r[i]=r[r[i]+1];
- }
PS: 1. 题目中height可能为0,初始化height数组为-1,防止死循环。
2. 结果可能超出int,height初始为__int64 或运算前强转化为__int64。运算过程中int会溢出。
【代码】
#include <cstdio>
#include <cstring>
#define maxn 100010
int l[maxn],r[maxn],n,i;
int main()
{
__int64 a[maxn],max,area;
while(scanf("%d",&n)&&n!=0){
for(i=1;i<=n;i++){
scanf("%I64d",&a[i]);
l[i]=r[i]=i;//l[i]表示左边边界,r[i]表示右边边界
}
a[0]=a[n+1]=-1;
for(i=1;i<=n;i++)
while(a[l[i]-1]>=a[i])
l[i]=l[l[i]-1];
for(i=n;i>=1;i--)
while(a[r[i]+1]>=a[i])
r[i]=r[r[i]+1];
for(i=1,max=0;i<=n;i++){
area=(r[i]-l[i]+1)*a[i];
max=area>max?area:max;
}
printf("%I64d\n",max);
}
return 0;
}