uvalive 3695

题意:给出了n个点的左边,问找一个矩形,使矩形边界上的点最多。

题解:枚举上下边界,然后从左到右扫一遍,left[i]存了第i条竖线左边上下边界有多少个点,然后onl[i]和onr[i]存竖线i上有几个点(前者不包含上下边界),那么矩形上的点就是left[j] - left[i] + onl[i] + onr[j],使onl[i] - left[i]最大就可以得到最大值。


#include 
#include 
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;
}

你可能感兴趣的:(ACM-DP)