题意:给出了n个点的左边,问找一个矩形,使矩形边界上的点最多。
题解:枚举上下边界,然后从左到右扫一遍,left[i]存了第i条竖线左边上下边界有多少个点,然后onl[i]和onr[i]存竖线i上有几个点(前者不包含上下边界),那么矩形上的点就是left[j] - left[i] + onl[i] + onr[j],使onl[i] - left[i]最大就可以得到最大值。
#include <stdio.h>
#include <algorithm>
using namespace std;
const int N = 110;
struct P {
int x, y;
}p[N];
int n, cnt, left[N], onl[N], onr[N], y[N];
int cmp(P a, P b) {
return a.x < b.x;
}
int solve() {
sort(p, p + n, cmp);
sort(y, y + n);
cnt = unique(y, y + n) - y;
if (cnt <= 2)
return n;
int res = 0;
for (int i = 0; i < cnt; i++)
for (int j = i + 1; j < cnt; j++) {
int y1 = y[i], y2 = y[j], k = 0;
for (int l = 0; l < n; l++) {
if (l == 0 || p[l].x != p[l - 1].x) {
k++;
onl[k] = onr[k] = 0;
left[k] = left[k - 1] + onr[k - 1] - onl[k - 1];
}
if (p[l].y > y1 && p[l].y < y2)
onl[k]++;
if (p[l].y >= y1 && p[l].y <= y2)
onr[k]++;
}
if (k <= 2)
return n;
int temp = 0;
for (int l = 1; l <= k; l++) {
res = max(res, left[l] + onr[l] + temp);
temp = max(temp, onl[l] - left[l]);
}
}
return res;
}
int main() {
int cas = 1;
while (scanf("%d", &n) && n) {
for (int i = 0; i < n; i++) {
scanf("%d%d", &p[i].x, &p[i].y);
y[i] = p[i].y;
}
printf("Case %d: %d\n", cas++, solve());
}
return 0;
}