https://ac.nowcoder.com/acm/contest/52441/F
- 考虑到是格点图,不存在三个点能构成等边三角形,即无需考虑等边三角形的去重。
- 对于一个等腰三角形,去枚举这个等腰三角形的顶点p,对于这个顶点,再开一个距离的桶cnt,cnt[m]为到这个顶点距离为m的点的个数。再去枚举其他的点q,在枚举过程中的cnt[dij(p,q)]即为对答案的贡献。最后考虑共线的情况,即反方向延长,看延长出的点有没有在输出中出现过即可,记录次数为line,最后的答案要减去line*2,因为会计算两次。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n;
struct node{
int x,y;
}arr[3050];
int vis[4000][4000];
int cnt[3000010];
int dij(int i,int j){
return (arr[i].x-arr[j].x)*(arr[i].x-arr[j].x)+(arr[i].y-arr[j].y)*(arr[i].y-arr[j].y);
}
int main(){
cin>>n;
for(int i = 1;i<=n;i++) {
cin>>arr[i].x>>arr[i].y;
vis[arr[i].x+1500][arr[i].y+1500] = 1;
}
int ans = 0;
int line = 0;
for(int i = 1;i<=n;i++){
for(int j = 1;j<=n;j++){
if(i==j) continue;
ans += cnt[dij(i,j)];//枚举到当前这个点时,前面到顶点距离为dij(i,j)的点出现的次数
cnt[dij(i,j)]++;//次数++
if(vis[arr[i].x-(arr[j].x-arr[i].x)+1500][arr[i].y-(arr[j].y-arr[i].y)+1500])
//检查共线的情况
line++;
}
for(int j = 1;j<=n;j++){
if(i==j) continue;
cnt[dij(i,j)] = 0;
}
}
cout<<(ans-line/2);
}