UVALive 3695 Distant Galaxy(枚举)

题意:给出平面上的n个点,找出一个矩形,使得边界上包含尽量多的点。

思路:直接离散化暴力的话复杂度是O(n^4),考虑离散化后原图形就变成了一个矩形,其中有点的位置值为1,没有点的位置值为0。

这就转化成了求子矩阵中边界上点最多的问题,先处理出每一列前j行的前缀和sumv[i][j],然后枚举任意两行,假设当前枚举的是第p行和第q行,第i列开口向右的u型上的点数为U[i],那么答案就是max(U[j]-U[i]+sumv[i][q]-sumv[i][p-1]+sumv[i][q-1]-sumv[i][p])。注意到-U[i]+sumv[i][q]-sumv[i][p-1]+sumv[i][q-1]-sumv[i][p]这一部分和当前枚举的第j列是没有关系的,所以维护它的最大值即可。时间复杂度为O(n^4)。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define eps 1e-6
#define LL long long
#define pii pair
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

const int MAXN = 110;
int n;
int h, l, line[MAXN], sumv[MAXN][MAXN], G[MAXN][MAXN];
struct Point {
	int x, y;
} p[MAXN];
int tmpx[MAXN], tmpy[MAXN];
int main() {
    //freopen("input.txt", "r", stdin);
    int kase = 0;
	while(cin >> n && n) {
		memset(G, 0, sizeof(G));
		memset(sumv, 0, sizeof(sumv));
		for(int i = 1; i <= n; i++) {
			scanf("%d%d", &p[i].x, &p[i].y);
			tmpx[i] = p[i].x;
			tmpy[i] = p[i].y;
		}
		sort(tmpx+1, tmpx+n+1);
		sort(tmpy+1, tmpy+n+1);
		h = unique(tmpx+1, tmpx+n+1) - tmpx - 1;
		l = unique(tmpy+1, tmpy+n+1) - tmpy - 1;
		for(int i = 1; i <= n; i++) {
			p[i].x = lower_bound(tmpx+1, tmpx+h+1, p[i].x) - tmpx;
			p[i].y = lower_bound(tmpy+1, tmpy+l+1, p[i].y) - tmpy;
			G[p[i].x][p[i].y]++;
		}
		for(int i = 1; i <= l; i++) 
			for(int j = 1; j <= h; j++) sumv[i][j] = sumv[i][j-1] + G[j][i];
		int ans = 0;
		for(int i = 1; i <= h; i++) {
			int tmp = 0;
			for(int j = 1; j <= l; j++) tmp += G[i][j];
			ans = max(ans, tmp);
			for(int j = i+1; j <= h; j++) {
				int tmp1 = 0, tmp2 = 0;
				for(int k = 1; k <= l; k++) {
					tmp1 += sumv[k][j] - sumv[k][i-1];
					ans = max(ans, tmp1 + tmp2);
					tmp1 = tmp1 - (sumv[k][j-1] - sumv[k][i]);
					tmp2 = max(tmp2, sumv[k][j]-sumv[k][i-1]-tmp1);
				}
			}
		}
		printf("Case %d: %d\n", ++kase, ans);
	}
    return 0;
}



















你可能感兴趣的:(程序设计竞赛)