POJ 1156

题意:求矩形中差异值最大不超过c的子矩阵的最大面积。

题解:枚举子矩形左右两列,然后记录每行位于这两列之间的最大最小值,建两个单调队列,从上往下一次扫描时,判断差异值是否超过了c,以此来维护队列,再加最优化剪枝。

View Code
#include<cstdio>

#include<cstring>

#include<algorithm>

using namespace std;

const int N=705;

int row,col,c;

int map[N][N],_min[N],_max[N];//min/max:第i行[a,b]区间最大/小值

int Q1[N*2],Q2[N*2],f1,f2,r1,r2;

void push1(int k)

{

    while(f1<=r1&&_min[Q1[r1]]>_min[k])

        r1--;

    Q1[++r1]=k;

}

void push2(int k)

{

    while(f2<=r2&&_max[Q2[r2]]<_max[k])

        r2--;

    Q2[++r2]=k;

}

int main()

{

    while(scanf("%d%d%d",&col,&row,&c)!=EOF)

    {

        for(int i=0;i<row;i++)

            for(int j=0;j<col;j++)

                scanf("%d",&map[i][j]);

        int ans=0;

        for(int i=0;i<col;i++)

        {

            for(int j=0;j<row;j++)

                _min[j]=_max[j]=map[j][i];

            for(int j=i+1;j<col&&j-i<100;j++)

            {

                for(int k=0;k<row;k++)

                {

                    _min[k]=min(_min[k],map[k][j]);

                    _max[k]=max(_max[k],map[k][j]);

                }

                f1=f2=0;

                r1=r2=-1;

                int w=j-i+1;

                for(int r=0,f=0;r<row&&(row-f)*w>ans;r++)

                {

                    push1(r);

                    push2(r);

                    while(f<=r&&f1<=r1&&f2<=r2&&_max[Q2[f2]]-_min[Q1[f1]]>c)

                    {

                        f++;

                        while(f2<=r2&&Q2[f2]<f)

                            f2++;

                        while(f1<=r1&&Q1[f1]<f)

                            f1++;

                    }

                    ans=max(ans,w*(r-f+1));

                }

            }

        }

        printf("%d\n",ans);

    }

    return 0;

}

 

你可能感兴趣的:(poj)