数矩形题解
这是一道对本蒟蒻来说比较难的题,经过了好几次改错才做出来,关键其实在于你到底敢不敢打,因为复杂度需要你的勇气。
20 分思路
这也是像我一样的普通选手在测试的时候的思路,我们发现四层枚举 for 循环是会被卡死的,甚至
优化思路
其实还是考察数学知识的问题。我们来观察矩形的特点。
矩形具有对角线等长,且对角线互相平分的特点。所以,我们处理出
通往正解之路
其实上述思路就是正解,只不过只像优化的思路那样想,还会有问题。
复杂度
我们可以计算这样的复杂度仍然很高,考虑优化。可以对线段的长度先排序,就会得到有序的以长度为关键字排序的线段序列(不保险的话可以以中点坐标为第 2 关键字进行排序,实测没有第二关键字容易被卡常),然后不符合匹配情况时直接跳出就行了。这样能节省不少时间。但还是有问题:万一长度相同的线段有很多条呢?三点可以确定一个圆(不共线),而这样算的话,圆的数量其实最多也就
如何拒绝精度问题
我在平时打代码的时候十分讨厌这种数学问题带来的精度问题,所以我在不断探索和请教中得出了两个方法。其一是在求中点和线段长度时不必开方或者除以
那么自然而然矩形的便是:
其中三个点的坐标可以随便取。这样一来就完美解决了精度问题。
最后的挣扎
在 debug 过程中,我的最后一步错在了没有 define int long long。我想提醒的是,如果真的脑子糊了想不清楚或者还怕出问题,先放上 define int long long 再说吧。(如果你在卡常当我没说)最后是代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
template< typename T > inline void read(T &x){
char c=getchar();x=0;int f=0;
for(;!isdigit(c);c=getchar()) f|=(c=='-');
for(;isdigit(c);c=getchar()) x=((x<<3)+(x<<1)+(c^48));
x=f?-x:x;
}
int n;
struct node{
int ax,ay;
int bx,by;
long long d;
long long cx,cy;
};
node l[2250010];
int tot;
struct Node{
int x,y;
};
Node wsl[1510];
bool cmp(node a,node b){
if(a.d==b.d)
{
if(a.cx==b.cx)return a.cy>b.cy;
return a.cx>b.cx;
}
return a.d>b.d;
}
long long ans=0;
signed main(){
scanf("%lld",&n);
for(int i=1;i<=n;i++){
read(wsl[i].x);
read(wsl[i].y);
}
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
l[++tot].cx=wsl[i].x+wsl[j].x;
l[tot].cy=wsl[i].y+wsl[j].y;
l[tot].ax=wsl[i].x,l[tot].ay=wsl[i].y;
l[tot].bx=wsl[j].x,l[tot].by=wsl[j].y;
l[tot].d=1ll*(wsl[i].x-wsl[j].x)*(wsl[i].x-wsl[j].x)+(wsl[i].y-wsl[j].y)*(wsl[i].y-wsl[j].y);
}
}//处理每条线段信息
sort(l+1,l+1+tot,cmp);
for(int i=1;i<tot;i++){
for(int j=i+1;j<=tot;j++){
if(l[i].d!=l[j].d||l[i].cx!=l[j].cx||l[i].cy!=l[j].cy)break;//不符合直接跳出
if(l[i].cx==l[j].cx&&l[i].cy==l[j].cy){
int wx=l[i].ax,wy=l[i].ay;
int sx=l[i].bx,sy=l[i].by;
int lx=l[j].ax,ly=l[j].ay;
ans=max(ans,1ll*(abs(wx*sy+sx*ly+lx*wy-wy*sx-sy*lx-ly*wx)));//三角形坐标面积公式
}
}
}
printf("%lld",ans);
return 0;
}
在考试以及下来 debug 的过程中有诸多收获,所以分享给诸君了!