首先枚举矩形的上下两边的坐标,然后求出在这两条边之间的所有悬线
on1[i]表示悬线 上包括端点有多少个点,on2[i]表示悬线i上不包括端点有多少个点
lf[i]表示悬线i左边在矩形上有多少个点
那么最终的结果就是求
i,j 使 lf[i] - lf[j] + on1[i] + on2[j] 最大,这里是DP,但是需要单调队列来优化(是单调队列的思想吧。。。)
AC代码如下:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
#define MAX 0x3f3f3f3f
struct Point{
int x, y;
bool operator<( const Point b ) const {
return x < b.x;
}
};
int N;
Point p[110];
int lf[110], on1[110], on2[110], py[110];
int solve(){
sort( p, p + N );
sort( py, py + N );
int m = unique( py, py + N ) - py;
if( m <= 2 ) return N;
int ans = 0;
for( int i = 0; i < m; i++ ){
for( int j = i + 1; j < m; j++ ){
int k = 0, prex = -MAX, prenum = 0;
lf[0] = on1[0] = on2[0] = 0;
for( int l = 0; l < N; l++ ){
if( !( p[l].y >= py[i] && p[l].y <= py[j] ) ) continue;
if( p[l].x != prex ){
k++;
lf[k] = lf[k-1] + prenum;
prenum = 0;
prex = p[l].x;
on1[k] = on2[k] = 0;
}
if( p[l].y == py[i] || p[l].y == py[j] ){
prenum++;
}else{
on2[k]++;
}
on1[k]++;
}
int temp = 0;
for( int l = 1; l <= k; l++ ){//优化之后的,不优化的话不知道能不能过
ans = max( ans, lf[l] + on1[l] + temp );
temp = max( temp, on2[l] - lf[l] );
}
}
}
return ans;
}
int main(){
int Case = 1;
while( scanf( "%d", &N ) && N ){
for( int i = 0; i < N; i++ ){
scanf( "%d%d", &p[i].x, &p[i].y );
py[i] = p[i].y;
}
printf( "Case %d: %d\n", Case++, solve() );
}
return 0;
}