Vjudge传送门
题意:
是说给出一个平面上的n个点,现在要找一个矩形,使得边界上包含最多的矩形。
题解:
…平时做过找出一个固定大小的矩形然后找包含最多的星星的时候能包含多少颗星星,而没有做过这种题,当我思考了很久之后,终于发现了原来刘汝佳的题解写的很好…于是我看了题解,并且几乎是
copy
了一份代码
我们首先的想法是通过枚举上下边界来进行计算,也就是说我们枚举每一个纵坐标的值,然后在这两个纵坐标上搞事情,具体操作可以看刘汝佳的蓝书的
P53
,写的很好,然后大概是这样的操作:
我们枚举上下边界,也就是矩形的上下两条边的位置,然后固定这两条边所在的直线的位置,然后去寻找对于这样的上下边界,我们可以找到的最优的矩形,显然我们还需要找两条宽,也就是竖着的两条边,于是我们试着维护一下的几条信息
on[i]
数组,
on2[i]
数组,
left[i]
数组,
我们用left数组维护上下两条边从这个点开始往左数,而不包含这个点所含有的点数,用
on
数组维护在这一个横坐标,也就是这一条竖线上并且满足
y
坐标在上下两条线之间,注意是之间,也就是说不包括与上下两条线相交的点,而
显然对于一个n属于[1,100]的范围,复杂度显然是优美的,最终我们计算出来的时间复杂度是O(能过)
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN=100+10;
struct Point{
int x,y;
bool operator < (const Point& rhs) const{return x<rhs.x;}
}p[MAXN];
int n,m,y[MAXN],on[MAXN],on2[MAXN],Left[MAXN];
int solve(){
sort(p+1,p+n+1);
sort(y+1,y+n+1);
m=unique(y+1,y+n+1)-y;
if(m<=2) return n;
int ans=0;
for(register int a=1;a<=m;a++){
for(register int b=a+1;b<=m;b++){
int ymin=y[a],ymax=y[b];//下边界为ymin,上边界为ymax;
int k=0;
for(register int i=1;i<=n;i++){
if(i==1||p[i].x!=p[i-1].x){
k++;
on[k]=on2[k]=0;
Left[k]=Left[k-1]+on2[k-1]-on[k-1];
}
if(p[i].y>ymin&&p[i].y<ymax) on[k]++;
if(p[i].y>=ymin&&p[i].y<=ymax) on2[k]++;
}
if(k<=2) return n;
int M=0;
for(register int j=1;j<=k;j++){
ans=max(ans,Left[j]+on2[j]+M);
M=max(M,on[j]-Left[j]);
}
}
}
return ans;
}
int main(){
int kase=0;
while(scanf("%d",&n)==1&&n){
for(register int i=1;i<=n;i++){scanf("%d%d",&p[i].x,&p[i].y);y[i]=p[i].y;}
printf("Case %d: %d\n",++kase,solve());
}
return 0;
}