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

【输入格式】

输入的第一行为数据组数T。每组数据的第一行为整数n(1≤n≤100);以下n行每行两个整数,即各个点的坐标(坐标均为绝对值不超过109的整数)。输入结束标志为n=0。

【输出格式】

对于每组数据,输出边界点个数的最大值。

先贴题解的精妙预处理:

不难发现,除非所有输入点都在同一行或者同一列上(此时答案为n),最优矩形的4条边都至少有一个点(一个角上的点同时算在两条边上)。这样,我们可以枚举4条边界所穿过的点,然后统计点数。这样做的时间复杂度为O(n5)(统计点数还需要O(n)时间),无法承受。

和《子序列》一题类似,可以考虑部分枚举,即只枚举矩形的上下边界,用其他方法确定左右边界,过程如图1-31所示。

对于竖线i,我们用left[i]表示竖线左边位于上下边界上的点数(注意,不统计位于该竖线上的点),on[i]和on2[i]表示竖线上位于上下边界之间的点数(区别在于on[i]不统计位于上下边界上的点数,而on2[i]要统计)。这样,给定左右边界ij时,矩形边界上的点数为left[j]-left[i]+on[i]+on2[j]。当右边界j确定时,on[i]-left[i]应最大。

枚举完上下边界后,我们先花O(n)时间按照从左到右的顺序扫描一遍所有点,计算left、on[i]和on2[i]数组,然后枚举右边界j,同时维护on[i]-left[i](i<j)的最大值。这一步本质上等价于例题《开放式学分制》。

再讲解一下这题的离散化处理

给每个点一个新的坐标 x坐标 为其原x坐标的排序后位置

y坐标 为其原y坐标的排序后位置

对于对距离不敏感的点集问题 这样十分方便处理问题

贴代码:

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <ctime>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#define oo 0x13131313
const int maxn=100+5;
using namespace std;
struct point
{
int x,y;
};
point P[maxn];
int N;
int YN,XN;
int ans;
int FF[maxn][maxn];
int CE[maxn][maxn];
int UP[maxn][maxn];
void input()
{
YN=0;XN=0;
memset(FF,0,sizeof(FF));
memset(CE,0,sizeof(CE));
memset(UP,0,sizeof(UP));
for(int i=1;i<=N;i++)
scanf("%d%d",&P[i].x,&P[i].y);
}
int cmp1(const void *i,const void *j)
{
point *ii=(point *)i,*jj=(point *)j;
return ii->x-jj->x;
}
void getXN()
{
int i;
qsort(P+1,N,sizeof(P[1]),cmp1);
for(i=1;i<=N;i++)
{
if(P[i].x!=P[i-1].x)
{
XN++;
P[i-1].x=XN-1;
}
else P[i-1].x=XN;
}
P[N].x=XN;
}
int cmp2(const void *i,const void *j)
{
point *ii=(point *)i,*jj=(point *)j;
return ii->y-jj->y;
}
void getYN_FF()
{
int i;
qsort(P+1,N,sizeof(P[1]),cmp2);
for(i=1;i<=N;i++)
{
if(P[i].y!=P[i-1].y)
{
YN++;
P[i-1].y=YN-1;
}
else P[i-1].y=YN;
FF[P[i-1].x][P[i-1].y]++;
}
P[N].y=YN;
FF[P[N].x][P[N].y]++;
}
void get_UPCE()
{
for(int i=1;i<=XN;i++)
for(int j=1;j<=YN;j++)
{
CE[i][j]=CE[i][j-1]+FF[i][j];
UP[i][j]=UP[i-1][j]+FF[i][j];
}
}
int On[maxn],Left[maxn],On2[maxn];
void get_On_Left_On2(int a,int b)
{
memset(On,0,sizeof(On));
memset(Left,0,sizeof(Left));
memset(On2,0,sizeof(On2));
for(int i=1;i<=YN;i++)
{
On[i]=UP[b-1][i]-UP[a][i];
On2[i]=UP[b][i]-UP[a-1][i];
Left[i]=CE[a][i-1]+CE[b][i-1];
}
}
void solve()
{
ans=0;
int tempans=0,tempi=0;
for(int i=1;i<=XN;i++)
for(int i2=i+1;i2<=XN;i2++)
{
get_On_Left_On2(i,i2);
tempans=0;
for(int j=1;j<=YN;j++)
{
if(ans<Left[j]+On2[j]+tempans)
ans=Left[j]+On2[j]+tempans;
if(tempans<On[j]-Left[j])
tempans=On[j]-Left[j];
}
}
}
int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
int Case=0;
while(cin>>N&&N)
{
Case++;
input();
if(N<=3) {
printf("Case %d: %d\n",Case,N);
continue;
}
getXN();
getYN_FF();
get_UPCE();
solve();
printf("Case %d: %d\n",Case,ans);
}
}

【巧妙预处理系列+离散化处理】【uva1382】Distant Galaxy的更多相关文章

  1. 【巧妙预处理系列】【UVA1330】City game

    最大子矩阵(City Game, SEERC 2004, LA 3029) 给定一个m×n的矩阵,其中一些格子是空地(F),其他是障碍(R).找出一个全部由F组成的面积最大的子矩阵,输出其面积乘以3后 ...

  2. hdu Distant Galaxy(遥远的银河)

    Distant Galaxy Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  3. LA3695 Distant Galaxy

    Distant Galaxy https://vjudge.net/problem/UVALive-3695 You are observing a distant galaxy using a te ...

  4. 【poj3141】 Distant Galaxy

    http://poj.org/problem?id=3141 (题目链接) 题意 给出平面上n个点,找出一个矩形,使边界上包含尽量多的点. solution 不难发现,除非所有输入点都在同一行或同一列 ...

  5. uva 1382 - Distant Galaxy

    题目连接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=91208#problem/G 题意:  给出平面上的n个点,找出一个矩形,使得边 ...

  6. LA 3695 Distant Galaxy

    给出n个点的坐标(坐标均为正数),求最多有多少点能同在一个矩形的边界上. 题解里是构造了这样的几个数组,图中表示的很明白了. 首先枚举两条水平线,然后left[i]表示竖线i左边位于水平线上的点,on ...

  7. 【巧妙算法系列】【UVA 11384】 Help is needed for Dexter 正整数序列

    Help is needed for Dexter Time Limit: 3 Second Dexter is tired of Dee Dee. So he decided to keep Dee ...

  8. 【巧妙算法系列】【Uva 11464】 - Even Parity 偶数矩阵

    偶数矩阵(Even Parity, UVa 11464) 给你一个n×n的01矩阵(每个元素非0即1),你的任务是把尽量少的0变成1,使得每个元素的上.下.左.右的元素(如果存在的话)之和均为偶数.比 ...

  9. UVa LA 3695 - Distant Galaxy 前缀和,状态拆分,动态规划 难度: 2

    题目 https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_pr ...

随机推荐

  1. 针对各主流数据mysql、sqlserver、oracle中文乱码问题。

    针对各主流数据mysql.sqlserver.oracle当以编码格式gbk存放数据时,要注意字符串类型的字段,要采用宽字符串nvarchar存放,前提是当你的应用程序是utf8编码,而数据库是gbk ...

  2. Android窗口管理服务WindowManagerService显示窗口动画的原理分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8611754 在前一文中,我们分析了Activi ...

  3. NuGet学习笔记(2)——使用图形化界面打包自己的类库(转)

    上文NuGet学习笔记(1) 初识NuGet及快速安装使用说到NuGet相对于我们最重要的功能是能够搭建自己的NuGet服务器,实现公司内部类库的轻松共享更新.在安装好NuGet扩展后,我们已经能够通 ...

  4. .NET批量大数据插入性能分析及比较

    数据插入使用了以下几种方式 1. 逐条数据插入2. 拼接sql语句批量插入3. 拼接sql语句并使用Transaction4. 拼接sql语句并使用SqlTransaction5. 使用DataAda ...

  5. 《JavaScript 闯关记》之原型及原型链

    原型链是一种机制,指的是 JavaScript 每个对象都有一个内置的 __proto__ 属性指向创建它的构造函数的 prototype(原型)属性.原型链的作用是为了实现对象的继承,要理解原型链, ...

  6. 真机调试以及“Could not find Developer Disk Image”问题解决方案

    真机测试步骤 1.运行Xcode,Xcode打开后,点左上角菜单'Xcode',点'Preferences'. 2.在打开的窗口中,点'Accounts',切换到账号页,然后点下面的'+'号,在弹出菜 ...

  7. OpenCV——CvMatchShapes函数

    功能:根据计算比较两张图像Hu不变距(函数返回值代表相似度大小,完全相同的图像返回值是0,返回值最大是1) double cvMatchShapes(const void* object1, cons ...

  8. (转) class II

    Overloading operators   Classes, essentially, define new types to be used in C++ code. And types in ...

  9. js渲染的3d玫瑰

    参看下面链接: 程序员最美情人节礼物:JS渲染的3D玫瑰

  10. HDU-简单计算器-1237

    这道题我做了一天,把中缀表达式转化为后缀表达式,但遇到了储存的问题,考虑了好久,写出后又调试,弄了一天,下面说一下中缀表达式转换后缀表达式: 算法: 中缀表达式转后缀表达式的方法: 1.遇到操作数:直 ...