Largest Rectangle in a Histogram(直方图中的最大矩形面积)——FOJ2559
题目:http://poj.org/problem?id=2559
想法:WA了好多次,终于AC了。错误原因:1.s=(long long)b[l-1].h*b[l-1].w;要强制转换,因为h,w都是int型,而s是long long型,这个错误最后才找到。
2.矩形延伸变化,思路不清楚。
做法:看了大神的这个思路,膜拜了。算法叫 单调栈。
我复述一遍步骤吧,以2 1 4 5 1 3 3 为例。
首先定义结构体(h,w),h表示矩形的高度,w表示矩形的宽度。题目相当于从左到右给出宽度为1的矩形,求组成的最大的矩形面积。
1.栈空,(2,1)直接入栈。
2.(1,1,)准备入栈时,发现高度比栈顶(2,1)的h小,则矩形不能延续到(1,1)这个矩形,栈顶矩形,找出栈内现存的矩形,并计算面积、更新最大面积,面积s=2*1=2,更新最大面积max=2;
3.(2,1)出栈,此时栈空,(1,1)入栈前,变化为(1,1+1),即(1,2),再入栈(因为之间出栈的矩形(2,1),可以被现在要入栈的矩形(1,1)延伸为(1,2)这个大一点的矩形。)
4.(4,1)比栈顶(2,1)高,入栈,同理(5,1)入栈。
5.(1,1)高度小于栈顶(5,1),不可入栈。
6.将比(1,1)高的矩形(5,1)、(4,1)依次出栈。每个(h,w)出栈前,找出栈内现存的矩形,并计算面积、更新最大面积,s=5*1=5.max=5,(5,1)出栈;此时栈顶(4,1)更新为(4,1+1),(4,1)矩形向后延伸变大成大矩形(4,2),s=4*2=8,max=8,
(4,2)出栈。(为什么(4,2)可以直接更新?因为它一定可以往后延伸,而延伸出来的矩形一定比它本身大)
7.(1,1)该入栈了,入栈之前,它应该更新为(1,1+2),这里面的二是(4,2)里面的2,也就是最后出栈的那个矩形的宽度,因为(4,2)这个矩形可以变成(1,2)延伸过来和(1,1)构成(1,3)这个大一点的矩形。
8.更新好后由于要入栈的(1,3)和当前栈顶(1,3)h一样,这时就不用入栈了,把栈顶(1,3)更新为(1,3+2)即(1,5),即可,因为就相当于矩形变大了。
9.(1,3)比(1,4)高,入栈。
10.(1,3)与当前栈顶(1,3)一样高,栈顶更新为(3,1+1)即可。
11.(0,1)准备入栈(为了将前面的矩形全部出栈),将栈内(3,2)、(1,5)依次出栈,(3,2)准备出栈,s=3*2,max=8,(1,4),更新为(1,5+2),(3,2)出栈;(1,7)准备出栈,s=1*7=7。
12.(0,1)入栈,结束操作。
代码:
1 #include <stdio.h> 2 struct node 3 { 4 int h,w; 5 } a[100005],b[100005]; 6 long long max,s; 7 int main() 8 { 9 int i,n,l;//栈中元素个数l 10 freopen("1.txt","r",stdin); 11 while(~scanf("%d",&n)&&n) 12 { 13 max=0; 14 l=0; 15 for(i=0; i<n; i++) 16 { 17 scanf("%d",&a[i].h);//输入 18 a[i].w=1;//初始化 19 } 20 a[n].h=0; 21 a[n].w=1; 22 for(i=0; i<=n; i++) //最后(0,1)入栈前,所有元素都出栈了 23 { 24 if(l==0||a[i].h>b[l-1].h) //如果栈空、或准备入栈的矩形h>栈顶h,矩形可延续,直接入栈 25 { 26 b[l].h=a[i].h; 27 b[l].w=a[i].w; 28 l++;//长度加一 29 } 30 else if(a[i].h==b[l-1].h) //如果准备入栈的矩形h=栈顶h,矩形可延续,直接更新栈顶矩形w即可 31 { 32 b[l-1].w=b[l-1].w+a[i].w; 33 } 34 else //如果准备入栈的矩形h<栈顶h,矩形不可延续,要出栈 35 { 36 s=(long long)b[l-1].h*b[l-1].w;//栈顶矩形的面积 37 //printf("s=%lld\n",s); 38 max=(s>max)?s:max;//更新面积最大值 39 l--;//出栈 40 if(l&&a[i].h<b[l-1].h)//表示将会继续出栈 41 b[l-1].w=b[l-1].w+b[l].w;//更新栈顶元素,栈顶矩形变化延伸(当前栈顶矩形宽度加宽,加上原先栈顶宽度) 42 else 43 a[i].w=a[i].w+b[l].w;//准备入栈的矩形宽度加宽,加上出栈的矩形的宽度 44 i--; 45 } 46 } 47 printf("%lld\n",max); 48 } 49 return 0; 50 }