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<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
#include<ctime>
#define eps 1e-6
#define LL long long
#define pii pair<int, int>
//#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;
}


















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值