分析:
浅谈用极大化思想解决最大子矩阵问题
算法二的复杂度是n*m,显然这道题是不能承受的
那么我们只能看一下算法一了:
算法一的代码量明显多于算法二
主要分成两大部分:
一.x轴上
首先按照x坐标排序
第一面扫描我们从左到右,
miny表示最大向下扩展到的下边界,maxy表示最大向上扩展到的上边界,
dx表示矩阵的长,dy表示矩阵的宽,s表示矩阵的面积
针对每一个点,我们先向右扩展,
初始状态是:
miny=0; //默认能扩展到边界
maxy=m;
s=0;
需要注意的是再向右推的时候,我们要同时维护miny和maxy
就像论文中说的那样:
if (po[j].y<=po[i].y&&po[j].y>miny) miny=po[j].y;
if (po[j].y>=po[i].y&&po[j].y<maxy) maxy=po[j].y;
如图:
单纯这样转移完之后,我们发现有一块面积我们没有计算过:
所以在第一层循环中,我们需要再单独计算一下这块面积
之后我们再从后往前,向左扩展,重复上述操作
二.y轴上
进行完上述操作后,我们发现
还有一部分面积我们没有考虑到
我们把点按照y排序
那么每块的面积就是
dx=n;
dy=po[i].y-po[i-1].y;
s=dx*dy;
当然,第一个点和最后一个点需要特殊处理一下
这里写代码片
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m,num,maxy,miny,ans=0,dx,dy,s;
struct node{
int x,y;
};
node po[10000];
int cmp1(const node &a,const node &b)
{
return a.x<b.x;
}
int cmp2(const node &a,const node &b)
{
return a.y<b.y;
}
void doit()
{
int i,j,k;
sort(po+1,po+1+num,cmp1);
for (i=1;i<=num;i++)
{
miny=0,maxy=m,s=0;
for (j=i+1;j<=num;j++)
{
dx=po[j].x-po[i].x;
dy=maxy-miny;
s=dx*dy;
ans=max(ans,s);
if (po[j].y<=po[i].y&&po[j].y>miny) miny=po[j].y;
if (po[j].y>=po[i].y&&po[j].y<maxy) maxy=po[j].y;
}
dx=n-po[i].x;
dy=maxy-miny;
s=dx*dy;
ans=max(ans,s);
}
for (i=num;i>=1;i--)
{
miny=0,maxy=m,s=0;
for (j=i-1;j>=1;j--)
{
dx=po[i].x-po[j].x;
dy=maxy-miny;
s=dx*dy;
ans=max(ans,s);
if (po[j].y<=po[i].y&&po[j].y>miny) miny=po[j].y;
if (po[j].y>=po[i].y&&po[j].y<maxy) maxy=po[j].y;
}
dx=po[i].x;
dy=maxy-miny;
s=dx*dy;
ans=max(ans,s);
}
sort(po+1,po+1+num,cmp2);
for (i=1;i<=num;i++)
{
if (i==1) dy=po[i].y,s=n*dy,ans=max(ans,s);
if (i==num) dy=m-po[i].y,s=n*dy,ans=max(ans,s);
if (i>1)
{
dy=po[i].y-po[i-1].y;
s=n*dy;
ans=max(ans,s);
}
}
printf("%d",ans);
}
int main()
{
scanf("%d%d%d",&n,&m,&num);
if (num==0)
{
printf("%d",n*m);
return 0;
}
for (int i=1;i<=num;i++)
scanf("%d%d",&po[i].x,&po[i].y);
doit();
return 0;
}