有N个点,每加一个点,能组成多少个矩形。
4<=N<=1000,每个点横纵坐标的绝对值不会超过16000
由矩阵的性质得,当一个四边形为矩形时,它的两条对角线相等且平分。
那么不妨设有两条线段,端点坐标分别为(x1,y1)、(x2,y2) 和 (x3,y3)、(x4,y4),那么需要满足:
// 保证平分
1.x1+x2=x3+x4
2.y1+y2=y3+y4
// 保证相等
3.(x2-x1)^2+(y2-y1)^2=(x3-x4)^2,(x4-y4)^2 // 因为任何数的平方都是正数,所以就不需要abs了
我们可以假设这两条线段就是某个四边形的对角线,那么只要这两条对角线相等且平分,那么就能确定一个矩形的存在.
所以我们只需要记录每条线段的横坐标之和,纵坐标之和及两端点距离的平方,然后通过hash来判断多少条线段的横坐标之和、纵坐标之和、两端点距离的平方相等并记录答案即可。
1.读入并存储每个点,让这个点与之前的所有点构成线段.
2.hash判断之前有没有和这条线段的横坐标之和、纵坐标之和、两端点距离的平方相等的线段.
3.如果有,则记录答案;如果没有,则进行标记。
#include
#include
using namespace std;
const int Mod=3000017;
int n,x[100010],y[100010],h[Mod+10],ans=0,edge=0,num[Mod+10];
int read() {
int S=0,F=1;char C=getchar();
for(;C<'0' || C>'9';C=getchar()) if(C=='-') F=-1;
for(;C>='0' && C<='9';C=getchar()) S=(S<<3)+(S<<1)+C-48;
return S*F;
}
int main() {
n=read();
for(int i=1;i<=n;i++) {
x[i]=read(),y[i]=read();
for(int j=1;j
由于我的hash不够强大,所以只要强一点的数据就过不了了,所以我们需要进一步来强化hash。
map适用于字符串hash,然而这题不是字符串hash...所以过
即在时间和空间优秀的情况下,进行两次及以上次数的hash。
我们可以将被hash的值存储起来,如果原先hash的值不一样的话,就将它换一个模数。例如本题:
我们可以把不重复的每条线段的横坐标之和,纵坐标之和及两端点距离的平方记录下来。
然后每得到一个hash数就对其进行操作。
所以改进之后代码如下:
#include
using namespace std;
const int Mod=3000017;
int n,x[100010],y[100010],h[Mod+10],xx[Mod+10],yy[Mod+10],l[Mod+10],num[Mod+10],ans=0,edge=0;
int read() {
int S=0,F=1;char C=getchar();
for(;C<'0' || C>'9';C=getchar()) if(C=='-') F=-1;
for(;C>='0' && C<='9';C=getchar()) S=(S<<3)+(S<<1)+C-48;
return S*F;
}
int main() {
n=read();
for(int i=1;i<=n;i++) {
x[i]=read(),y[i]=read();
for(int j=1;j
将被hash数乘一个很大的数,让它爆unsigned long long的范围,然后它就会溢出,成为一个值。这个值就可以当做为hash值。