题解:P9423 [蓝桥杯 2023 国 B] 数三角
题目大意
给出 \(n\) 个点的坐标,求其中能围成等腰三角形的三个点有几组。
思路
发现 \(n\) 的范围不大,考虑先预处理出每两个点的距离,然后在找出可能成为等腰三角形的点的组数,最后去除多余情况。
实现细节
:::info[两点之间的距离公式]
点 \(a(x_1,y_1)\) 和点 \(b(x_2,y_2)\) 之间的距离为:
\[\sqrt{(x1-x2)^2+(y1-y2)^2}
\]
:::
- 距离的处理
对于两点之间的距离,我们有必要用浮点数去存储吗?实际上没有,因为如果一个数 \(S\) 确定了,那么 \(\sqrt{S}\) 也是固定的,所以我们只需要记录 \((x1-x2)^2+(y1-y2)^2\) 即可。 - 可能成为等腰三角形的点的组数
首先固定顶点,然后如果有 \(2\) 个点到这个点的距离相等,那么这 \(3\) 个点就可能组成等腰三角形。所以我们先把这种情况记录下来。 - 多余情况
多余情况无非有 \(2\) 种:
- 三点共线
- 等边三角形(这种不可能,具体原因自证)
:::info[中点坐标公式]
点 \(a(x_1,y_1)\) 和点 \(b(x_2,y_2)\) 中点的坐标为:
\[(\frac{x_1+x_2}{2},\frac{y_1+y_2}{2})
\]
:::
注意到,三点共线时一定保证其中一个点是另外两个点的中点,根据中点坐标公式判断即可。
- tru 的作用
作用很简单,记录每个点是否存在。 - 时间复杂度
首先考虑这两层循环:
for(int i=1;i<=n;++i){
cnt.clear();
for(int j=1;j<=n;++j){
...
}
}
复杂度 \(\mathcal{O}(n^2)\)。
然后是这两层:
for(int i=1;i<=n;++i){
for(int j=i+1;j<=n;++j)//保证i<j
...
}
注意到 \(i=1\) 时内层循环执行 \(n-1\) 次;
\(i=2\) 时内层循环执行 \(n-2\) 次;
\(i=3\) 时内层循环执行 \(n-3\) 次;
…
\(i=n\) 时内层循环执行 \(0\) 次;
所以这部分复杂度为 \(\mathcal{O}(\frac{n^2-n}{2})\)。
所以总复杂度为 \(\mathcal{O}(n^2+\frac{n^2-n}{2})\),可以通过此题。
#include <bits/stdc++.h>
#define ll long long
#define pii pair<int, int>
#define piii pair<pii, int>
#define pll pair<ll, ll>
#define plll pair<pll, ll>
#define pref static inline
#define fi first
#define se second
using namespace std;
const int MAXN=2005;
ll n,x[MAXN],y[MAXN],ans;
map<ll,int>cnt;
map<ll,map<ll,int>>tru;//记录(i,j)位置是否存在点
namespace heffo_hard{
pref ll dis_2(ll x1,ll y1,ll x2,ll y2){//点(x1,y1)和点(x2,y2)之间的距离,为了方便计算统一把距离定义成dis^2,由于在namespace内,所以y1不会冲突
return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
}
pref void solve(){
cin>>n;
for(int i=1;i<=n;++i){
cin>>x[i]>>y[i];
tru[x[i]][y[i]]=1;
}
for(int i=1;i<=n;++i){
cnt.clear();
for(int j=1;j<=n;++j){
ans+=cnt[dis_2(x[i],y[i],x[j],y[j])];
cnt[dis_2(x[i],y[i],x[j],y[j])]++;
}
for(int j=i+1;j<=n;++j)//保证i<j
if(!((x[i]+x[j])&1)&&!((y[i]+y[j])&1))
ans-=tru[x[i]+x[j]>>1][y[i]+y[j]>>1];//如果存在-1,不存在对ans没有影响
}
cout<<ans<<endl;
}
};
signed main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
heffo_hard::solve();
return 0;
}
/*
heffo_hard
*/

浙公网安备 33010602011771号