• HDU1506(最大子矩形)
    • 题意
      • 给你一个直方图,告诉你各个条形矩形的高度,求基线对齐构成的矩形中最大的矩形的面积
    • 题解
      • 单调栈或者dp
      • 单调栈做法已经写过题解了,所以写一下dp
      • h[i]表示第i个矩形的高
      • 对每个h[i]从两边分别找与i相邻的连续高于h[i]的矩阵个数
      • 然后取max(maxx,h[i]*[r[i]-l[i]+1])
    • 代码
      • #include<stdio.h>
        #include<string.h>
         
        int l[100010],r[100010];
        __int64 h[100010];
        int main()
        {
            int N;
            while(~scanf("%d",&N) && N!=0)
            {
                memset(h,0,sizeof(h));
                for(int i = 1; i <= N; i++)
                {
                    scanf("%I64d",&h[i]);
                    l[i] = r[i] = i;
                }
         
                l[0] = 1;
                r[N+1] = N;
                h[0] = -1;
                h[N+1] = -1;
                //这上边不加就会超时,不加的话下边就可能一直while,跳不出循环
                for(int i = 1; i <= N; i++)
                {
                    while(h[l[i]-1] >= h[i])//找位置i的左边界
                        l[i] = l[l[i]-1];
                }
                for(int i = N; i >= 1; i--)
                {
                    while(h[r[i]+1] >= h[i])//找位置i的右边界
                        r[i] = r[r[i]+1];
                }
                __int64 MaxArea = -0xffffff0;
                for(int i = 1; i <= N; i++)
                {
                    if(h[i]*(r[i]-l[i]+1) > MaxArea)
                        MaxArea = h[i]*(r[i]-l[i]+1);
                }
                printf("%I64d\n",MaxArea);
            }
            return 0;
        }
  • HDU1505(最大子矩阵)
    • 题意
      • 给你一个M*N的区域。R代表被占用,F代表空闲。每块空闲的区域价值3美金,求全部由空闲区域围成的矩形的价值
    • 题解
      • 与最大矩形一样,只不过我们需要加一维来遍历所有行
      • h[i][j]表示第i行第j个矩形的高
      • 对每个h[i][j]从两边分别找与j相邻的连续高于h[i][j]的矩阵个数
      • 然后取max(maxx,h[i][j]*[r[i]-l[i]+1])
    • 代码
      • #include<iostream>
        #include<cstdio>
        #include<cstring>
        #include<string>
        #include<set>
        #include<vector>
        #include<map>
        #include<stack>
        #include<queue>
        #include<cmath>
        #include<fstream>
        #include<algorithm>
        using namespace std;
        
        #define rep(i,a,n) for(int i=a;i<=n;i++)
        #define per(i,a,n) for(int i=n;i>=a;i--)
        //#define CLR(a) memset(a,0,sizeof(a))
        
        typedef long long ll;
        typedef unsigned long long ull;
        const double eps=1e-6;
        const int INF = 0x3f3f3f3f;
        const int maxn = 1010;
        int h[maxn][maxn];
        int l[maxn];
        int r[maxn];
        char g[10];
        
        int main(){
        	int t;
        	scanf("%d", &t);
        	while(t--){
        		int n,m;
        		scanf("%d%d", &n,&m);
        		rep(i,1,n){
        			rep(j,1,m){
        				scanf("%s", g);
        				if(g[0]=='F')h[i][j] = h[i-1][j]+1;
        				else h[i][j]=0;
        			}
        		}
        		int maxx = -INF;
        		rep(i,1,n){
        			l[0]=1;
        			r[m]=m;
        			h[i][0]=-1;
        			h[i][m+1]=-1;
        			rep(j,1,m){
        				l[j]=r[j]=j;
        			}
        			rep(j,1,m){
        				while(h[i][l[j]-1]>=h[i][j]) l[j]=l[j]-1;
        				while(h[i][r[j]+1]>=h[i][j]) r[j]=r[j]+1;
        			}
        			rep(j,1,m){
        				maxx=max(maxx,h[i][j]*(r[j]-l[j]+1));
        			}
        		}
        		printf("%d\n", maxx*3);
        	}
        	return 0;
        }
  • 总结
    • 其实很多一维dp转化为二维的时候就是将新增的一维遍历一遍,比如最大子矩阵和问题POJ1050

发表评论

邮箱地址不会被公开。 必填项已用*标注