四次循环必然超时就不说了..
两两分组遍历查找也超时了..
只能用HASH了,先两两计算前两个数的和放入HASH中..在两两计算后两个数的和,在HASH数组中找它的相反数..
这里用了链地址法,相对开放定址法之类的方法速度要快不少..
注意在HASH数组中要记录当前数的个数,因为会有重复的数.
开的HASH数组的容量是10000000,运行时间是1688MS.
#include <cstdio>
#include <string.h>
using namespace std;
struct array{//记录输入的数
int a,b,c,d;
}ar[4001];
struct Record{//HASH数组中的Record
int v;
int h;
Record *next;
}r[10000000];
void hash(int x){
x+=2<<29;//保证全部为整数
int pos=x%10000000;
if(r[pos].h==0){//如果这个位置没有放
r[pos].v=x;
r[pos].h=1;
}else if(r[pos].v==x){//如果这个位置放的就是要找的
r[pos].h++;
}else{//在链地址中查找
Record *s=&r[pos];
while(s->next){
if(x==s->next->v){//找到
s->next->h++;
}
s=s->next;
}
if(s->next==NULL){//未找到延长链
Record *q=new Record;
q->v=x;
q->h=1;
s->next=q;
q->next=NULL;
}
}
}
int find(int x){
x+=2<<29;
int pos=x%10000000;
if(r[pos].h==0){//该位置未放
return 0;
}else if(r[pos].v==x){//该为脂肪的就是要找的数
return r[pos].h;
}else{//在链中查找
Record *s=&r[pos];
while(s->next){
if(x==s->next->v){//找到
return s->next->h;
}
s=s->next;
}
if(s->next==NULL){//未找到
return 0;
}
}
}
int main(){
int n;
while(scanf("%d",&n)!=EOF){
int res=0;
for(int i=0;i<n;i++){
r[i].h=0;
r[i].next=NULL;
}
for(int i=0;i<n;i++){
scanf("%d%d%d%d",&ar[i].a,&ar[i].b,&ar[i].c,&ar[i].d);
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
hash(ar[i].a+ar[j].b);
}
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
res+=find(-(ar[i].c+ar[j].d));
}
}
printf("%d\n",res);
}
return 0;
}