uvalive 3695

来源:互联网 发布:至尊棋牌挂机软件 编辑:程序博客网 时间:2024/06/12 20:26

题意:给出了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;}

0 0