题意:

给出N个点,可以选其中四个点组成正方形,输出最大边长。其中

思路:

容易想到如果知道两个点这个正方形就可以确定,但是N*N明显不行,这里又可以有一个剪枝,只需要枚举同行或者同列的点。

对于每个点哈希一下存在unordered_set里。

两重循环,外层枚举一个点,内层枚举跟它同行或同列的点,然后确定边长,在unordered_set找另外两个点存不存在。这里还是有很多重复计算,比如

1和2算的时候其实已经算了1和3的情况了,所以可以选同行同列中size小的那个。

还可以加个最优解剪枝。

代码:

const ll base=1e9+7;
struct point
{
    int x,y;
}p[100010];
unordered_set<ll>s;
unordered_map<int,vector<int> >mpx,mpy;
int ans;
ll gethash(int x,int y)
{
    return x*base+y;
}
int judge1(int x,int y,int  z)
{
    int d=abs(y-z);
    if(d<=ans)return 0;
    //if(s.count(gethash(x-d,y))&&s.count(gethash(x-d,z)))
        //return d; 不用写否则会重复
    if(s.count(gethash(x+d,y))&&s.count(gethash(x+d,z)))
        return d;
    return 0;
}
int judge2(int x,int y,int z)
{
    int d=abs(y-z);
    if(d<=ans)return 0;
    //if(s.count(gethash(y,x-d))&&s.count(gethash(z,x-d)))
        //return d;
    if(s.count(gethash(y,x+d))&&s.count(gethash(z,x+d)))
        return d;
    return 0;
}
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        s.clear();mpx.clear();mpy.clear();
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&p[i].x,&p[i].y);
            mpx[p[i].x].push_back(p[i].y);
            mpy[p[i].y].push_back(p[i].x);
            s.insert(gethash(p[i].x,p[i].y));
        }
        ans=0;
        for(int i=1;i<=n;i++)
        {
            int len1=mpx[p[i].x].size();
            int len2=mpy[p[i].y].size();
            if(len1<len2)
            {
                for(int j=0;j<len1;j++)
                ans=max(ans,judge1(p[i].x,p[i].y,mpx[p[i].x][j]));
            }
            else
            {
                for(int j=0;j<len2;j++)
                ans=max(ans,judge2(p[i].y,p[i].x,mpy[p[i].y][j]));
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

树链剖分 Previous
HDU6415 推导/DP Next