这道题我用了扫描法,悬线法还没有填坑
首先想到尽量减少枚举量,也就是尽量让每个矩形都是有意义的,那么只有障碍点边缘有价值,所以只需要从左到右扫描一遍,得到的全部都是有意义的。
那么这种方法是否还有遗漏呢?
答案是肯定的
因为我们从左到右搜,肯定是以左边为准线,那么如果一直延伸到右边,那么如果是右边延伸到左边就会遗漏,同理,如果与左边界和右边界重合的矩形也会遗漏。
所以加入两个特判
1.从右边扫一遍,特判第一种情况
2.从上到下排序,相邻的两个点*横轴就是第二种情况
详细见代码
#include<bits/stdc++.h> #define max(a,b) (a>b?a:b) #define min(a,b) (a<b?a:b) using namespace std; int r,c,n,ans; struct node{int x,y;}a[5050]; bool cmp(node a,node b){return a.x<b.x;} bool cmp1(node a,node b){return a.y<b.y;} int main(){ scanf("%d%d%d",&r,&c,&n); for(int i=1;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y); a[++n].x=0;a[n].y=c;//注意的细节,为了方便处理 a[++n].x=0;a[n].y=0;//在矩形边界都设置了障碍点 a[++n].x=r;a[n].y=c; a[++n].x=r;a[n].y=0; sort(a+1,a+n+1,cmp); for(int i=1;i<=n;i++){//开始扫描 int up=0,dn=c,v=a[i].x; for(int j=i+1;j<=n;j++){//从左到右 ans=max(ans,(a[j].x-a[i].x)*(dn-up));//能延伸的最大子矩阵 if(a[i].y==a[j].y)break; if(a[j].y>a[i].y)dn=min(dn,a[j].y);//修改上下边界 else up=max(up,a[j].y); } up=0;dn=c;v=r-a[i].x; for(int j=i-1;j;j--){//从右到左 ans=max(ans,(a[i].x-a[j].x)*(dn-up)); if(a[i].y==a[j].y)break; if(a[j].y>a[i].y)dn=min(dn,a[j].y); else up=max(up,a[j].y); } } sort(a+1,a+n+1,cmp1); for(int i=1;i<n;i++)ans=max(ans,(a[i+1].y-a[i].y)*r);//特判第二种情况 printf("%d ",ans); }