您的位置:首页 > 大数据 > 人工智能

Shanghai 2006,UVaLive(LA) 3695 Distant Galaxy题解

2017-09-06 18:26 357 查看

Vjudge传送门

题意:

是说给出一个平面上的n个点,现在要找一个矩形,使得边界上包含最多的矩形。

题解:

…平时做过找出一个固定大小的矩形然后找包含最多的星星的时候能包含多少颗星星,而没有做过这种题,当我思考了很久之后,终于发现了原来刘汝佳的题解写的很好…于是我看了题解,并且几乎是copy了一份代码

我们首先的想法是通过枚举上下边界来进行计算,也就是说我们枚举每一个纵坐标的值,然后在这两个纵坐标上搞事情,具体操作可以看刘汝佳的蓝书的P53,写的很好,然后大概是这样的操作:

我们枚举上下边界,也就是矩形的上下两条边的位置,然后固定这两条边所在的直线的位置,然后去寻找对于这样的上下边界,我们可以找到的最优的矩形,显然我们还需要找两条宽,也就是竖着的两条边,于是我们试着维护一下的几条信息

on[i]数组,on2[i]数组,left[i]数组,

我们用left数组维护上下两条边从这个点开始往左数,而不包含这个点所含有的点数,用on数组维护在这一个横坐标,也就是这一条竖线上并且满足y坐标在上下两条线之间,注意是之间,也就是说不包括与上下两条线相交的点,而on2就是包含相交的点的数组,显然对于一个矩形,我们的答案应该是left[j]−left[i]+on2[j]+on[i],大家稍微模拟一下就可以了,然后我们就可以先愉快地推这些数组,然后可以维护一个东西,那就是我们如果固定了一个j,那么显然我们只需要找一个on[i]−left[i]的最大值,因为我们其他的信息都是固定的,所以我们类似于之前做的那道题[OpenCreditSystem,UVa11078],在计算的同时维护就可以了,所以就可以很愉快地转移啦

显然对于一个n属于[1,100]的范围,复杂度显然是优美的,最终我们计算出来的时间复杂度是O(能过)

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN=100+10;
struct Point{
int x,y;
bool operator < (const Point& rhs) const{return x<rhs.x;}
}p[MAXN];
int n,m,y[MAXN],on[MAXN],on2[MAXN],Left[MAXN];
int solve(){
sort(p+1,p+n+1);
sort(y+1,y+n+1);
m=unique(y+1,y+n+1)-y;
if(m<=2) return n;
int ans=0;
for(register int a=1;a<=m;a++){
for(register int b=a+1;b<=m;b++){
int ymin=y[a],ymax=y[b];//下边界为ymin,上边界为ymax;
int k=0;
for(register int i=1;i<=n;i++){
if(i==1||p[i].x!=p[i-1].x){
k++;
on[k]=on2[k]=0;
Left[k]=Left[k-1]+on2[k-1]-on[k-1];
}
if(p[i].y>ymin&&p[i].y<ymax)   on[k]++;
if(p[i].y>=ymin&&p[i].y<=ymax) on2[k]++;
}
if(k<=2) return n;
int M=0;
for(register int j=1;j<=k;j++){
ans=max(ans,Left[j]+on2[j]+M);
M=max(M,on[j]-Left[j]);
}
}
}
return ans;
}
int main(){
int kase=0;
while(scanf("%d",&n)==1&&n){
for(register int i=1;i<=n;i++){scanf("%d%d",&p[i].x,&p[i].y);y[i]=p[i].y;}
printf("Case %d: %d\n",++kase,solve());
}
return 0;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: