前言

CSP-J 模拟赛教练放的一道原题,赛时 AC 了听同学说洛谷有,回来写题解。

题目思路

如何找到正方形的四个顶点

最简单的最容易思考到的方法:$\mathcal O(n^4)$ 或 $\mathcal O(n^3)$ 枚举四个顶点。

但由于 $n\leq3000$,肯定超时,复杂度肯定要控制在 $\mathcal O(n^2)$ 左右。

$\mathcal O(n^2)$ 意味着枚举两个点,我们来观察一下这两个点与另外两个点的位置关系。

如图所示,我们将左上顶点定为 $i$,左下顶点对应 $j$,那么可以发现如下关系:

  1. 标红段为 $i$ 与 $j$ 的横坐标差,正好为左下顶点与右下顶点的纵坐标之差。
  2. 标蓝段为 $i$ 与 $j$ 的纵坐标差,正好为左下顶点与右下顶点的横坐标之差。

如此,我们即可仅仅通过两个点推出其余两个点的坐标。

如何求面积

前置知识:勾股定理 $a^2+b^2=c^2$。

把连接 $i$ 和 $j$ 的虚线以及红蓝两线当做一个直角三角形,我们把蓝线想成 $a$,红线想成 $b$,那么虚线长度即正方形的边长,即为 $\sqrt{a^2+b^2}$。再根据正方形面积公式,正方形面积为 $\sqrt{a^2+b^2}\times \sqrt{a^2+b^2}=a^2+b^2$。

完整代码

#include<bits/stdc++.h>
#define max(a,b) a>b?a:b
using namespace std;
bool f[5020][5020];
int x[3020];
int y[3020];
int n,m;
int main()
{
//  freopen("ruin.in","r",stdin);
//  freopen("ruin.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",x+i,y+i);
        f[x[i]][y[i]]=1;
    }
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {

            int a=x[i]-x[j];
            int b=y[i]-y[j];
            int Ax=x[i]-b;
            int Bx=x[j]-b;
            int Ay=y[i]+a;
            int By=y[j]+a;  
            if(Ax<1||Ax>5000||Bx<1||Bx>5000||Ay<1||Ay>5000||By<1||By>5000)continue;
            if(f[Ax][Ay]&&f[Bx][By])
            {
                ans=max(ans,a*a+b*b);
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}
最后修改:2023 年 04 月 23 日
v我50吃疯狂星期四