LA 3695遥远的银河

题目大意
给定平面上的n个点,找一个矩形,使得边界上包含尽量多的点。
分析
不难发现除非所有的点都在同一条直线上,否则矩阵的四条边至少会有一个点(一个角上的点同时算在两条边上).这样,我们枚举4条边界所穿过的点,然后统计点数,这样做的复杂符很高,数据量无法承受。
和子序列一样我们考虑部分枚举,只枚举矩形的上下界。用其他方法定义左右边界。

当一个矩形的上下边界确定后,我们来计算左右边界点。我们定义left(i)为以i为右边界的上下边界的数,定义on(i)和on2(i)为边界本身不属于上下边界的点以及算上下边界的点;这样对于一个矩形,总点数为left(j)-left(i)+on(i)+on(j) (j>i) 我们进一步的优化 当边界j 确定是 on(i)-left(i)应为最大
上代码

#include<iostream>
#include<algorithm>
#include<cstdio>
#define maxn 100+10
using namespace std;

struct po {
	int x, y;
	bool operator <(const po& a) const
	{
		return x < a.x;
	}
};
po   star[maxn];
int le[maxn], on[maxn], on2[maxn];
int y[maxn];
int n;
int  solve()
{
	int ymin, ymax;
	sort(star, star + n);
	sort(y, y + n);
	//print();
	int num = unique(y, y + n)-y;
	//cout << num<<endl;
	if (num <= 2)
		return n;
	int ans=0, M=0;
	for (int a = 0; a <num; a++)
	{
		for (int b = a + 1; b < num; b++)
		{


			 int k = 0;
			ymin = y[a], ymax = y[b];
			le[0] = 0;
			for (int i = 0; i < n; i++)
			{
				if (i == 0 || star[i].x != star[i - 1].x)    //一条新的竖线
				{
					k++;
					on[k] = on2[k] = 0;
					le[k] =le[k - 1] + on2[k - 1] - on[k-1];//为什么k要等于0;
				}
				if (star[i].y > ymin&&star[i].y < ymax) on[k]++;
				if (star[i].y >= ymin&&star[i].y <= ymax) on2[k]++;
			}
			if (k <= 2)
				return n;
			M = 0;
			for (int j = 1; j <=k; j++)
			{
				ans = max(ans, le[j] + on2[j] + M);
				M = max(M, on[j] - le[j]);
			}
		}
	}
	return ans;
}

int main()
{
	int k = 1;
	while (cin >> n && n != 0)
	{
		for (int i = 0; i < n; i++)
		{
			cin >> star[i].x >> star[i].y;
			y[i] = star[i].y;
		}
		printf("Case %d: %d\n", k++, solve());
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值