思路:
先离散化。
令 lft [i] [j] 为 第i行前j列点的个数和, sum [i] [j] 为第j列前i行点的个数和。
枚举上下边界,记作 x=i、x=j 。
令 on [k] 为 以 (i,k) (j,k) 为端点的线段当的点数和(不包括端点),计算方法是 on[k]=sum[j-1][k]-sum[i][k]。
假设 s(i,j) 为以 (i,x) (j,y) (i,y) (j,x) 为顶点的矩形边上的点数( i<j , x<y ),可知:
s(i,j)max
= (on(x)+on(y)+lft(i,y)-lft(i,x-1)+lft(j,y)-lft(j,x-1))max
= (on(y)+lft(i,y)+lft(j,y))max - (lft(i,x-1)+lft(j,x-1)-on(x))min
为了方便,令 a[y]=on[y]+lft[i][y]+lft[j][y] , b[x]=lft[i][x-1]+lft[j][x-1]-on[x] ,问题就转化成了求两个整数 x,y (x<y),使得a[y]-b[x]的值最大。
此时只需从小到大枚举y,在每枚举到一个y时,顺便计算出一个小于y的使得b[x]最小的x就可以了。
注意:
1、坐标有负数。
2、当所有点在同一行或同一列时,要特殊判断。
3、on的计算,这里不能包括上下的端点。
代码:
#include<bits/stdc++.h>
using namespace std;
#define maxn 100
struct Point {
int x,y;
Point(int xx=0,int yy=0) {
x=xx,y=yy;
}
};
int n;
int cntr,cntc; //不同的横坐标的个数,不同的纵坐标的个数。即离散化后的图的长和宽
bool g[maxn+5][maxn+5];
int lft[maxn+5][maxn+5]; //第i行前j列点的个数和
int sum[maxn+5][maxn+5]; //第j列前i行点的个数和
void init() {
cntr=cntc=0;
memset(g,0,sizeof(g));
memset(lft,0,sizeof(lft));
memset(sum,0,sizeof(sum));
}
void readin() {
Point a[maxn+5];
int row[maxn+5],col[maxn+5];
for(int i=1; i<=n; i++) {
scanf("%d%d",&a[i].x,&a[i].y);
row[i]=a[i].x,col[i]=a[i].y;
}
//离散化
sort(row+1,row+n+1),sort(col+1,col+n+1);
map<int,int> mpr,mpc;
for(int i=1; i<=n; i++) {
if(!mpr.count(row[i])) cntr++,mpr[row[i]]=cntr;
}
for(int i=1; i<=n; i++) {
if(!mpc.count(col[i])) cntc++,mpc[col[i]]=cntc;
}
for(int i=1; i<=n; i++) {
a[i]=Point(mpr[a[i].x],mpc[a[i].y]);
g[a[i].x][a[i].y]=true;
}
}
void make_lft() {
for(int i=1; i<=cntr; i++) {
for(int j=1; j<=cntc; j++) {
lft[i][j]=lft[i][j-1];
if(g[i][j]) lft[i][j]++;
}
}
}
void make_sum() {
for(int j=1; j<=cntc; j++) {
for(int i=1; i<=cntr; i++) {
sum[i][j]=sum[i-1][j];
if(g[i][j]) sum[i][j]++;
}
}
}
void make_on(int x,int y,int *on) {
for(int i=1; i<=cntc; i++) {
on[i]=sum[y-1][i]-sum[x][i];
}
}
void make_a(int i,int j,int *on,int *a) {
for(int y=1; y<=cntc; y++) {
a[y]=on[y]+lft[i][y]+lft[j][y];
}
}
void make_b(int i,int j,int *on,int *b) {
for(int x=1; x<=cntc; x++) {
b[x]=lft[i][x-1]+lft[j][x-1]-on[x];
}
}
int main() {
int T=0;
while(~scanf("%d",&n)&&n) {
init();
readin();
make_lft();
make_sum();
int ans=0;
if(cntr==1||cntc==1) ans=n;
else for(int i=1; i<=cntr; i++) { //枚举上下边界
for(int j=i+1; j<=cntr; j++) {
int on[maxn+5]= {0};
make_on(i,j,on);
int a[maxn+5],b[maxn+5]; //a[y]=on[y]+lft[i][y]+lft[j][y],b[x]=lft[i][x-1]+lft[j][x-1]-on[x]
make_a(i,j,on,a),make_b(i,j,on,b);
int x=1;
for(int y=2; y<=cntc; y++) {
ans=max(a[y]-b[x],ans);
if(b[y]<b[x]) x=y;
}
}
}
printf("Case %d: %d\n",++T,ans);
}
return 0;
}