题意:
平面上n个点,问能组成多少个锐角三角形
题解的方法就比较好
统计锐角的个数,设为
A
,钝角和直角的个数,设为
B
每个锐角三角形有三个锐角,每个钝角和直角三角形均贡献两个锐角
所以答案即为
A−2B3
然后题解在对每个点极角排序之后,采用 two pointers的方式来找上下界
比二分好写多了,也很方便,时间复杂度
O(N2logN)
代码一:
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define N 2005
const double pi=acos(-1.0);
int n;
struct node
{
double x, y;
}p[N];
double ang[N*2];
void solve()
{
for(int i=1; i<=n; i++) cin>>p[i].x>>p[i].y;
LL ans1=0, ans2=0;
for(int i=1; i<=n; i++)
{
int cnt=0;
for(int j=1; j<=n; j++)
{
if(i==j) continue;
ang[++cnt]=atan2(p[i].y-p[j].y, p[i].x-p[j].x);
if(ang[cnt]<0) ang[cnt]+=2*pi;
}
sort(ang+1, ang+cnt+1);
for(int j=1; j<=cnt; j++) ang[j+cnt]=ang[j]+2*pi;
LL l=1, r=1, len=1;
for(int j=1; j<=cnt; j++)
{
while(r<2*cnt&&ang[r]-ang[j]<pi) r++;
while(l<2*cnt&&ang[l]-ang[j]<0.5*pi) l++;
while(len<2*cnt&&ang[j]==ang[len]) len++;
ans1+=l-len;
ans2+=r-l;
}
}
printf("%I64d\n", (ans1-2*ans2)/3);
}
int main()
{
while(cin>>n)
{
solve();
}
return 0;
}
代码二:
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define N 2005
const double pi=acos(-1.0);
const double eps=1e-12;
int n;
int sgn(double x)
{
return x>eps?1:(x<-eps?(-1):0);
}
struct node
{
double x, y;
node operator -(const node&other)const
{
return {x-other.x, y-other.y};
}
}p[N];
double ang[N*2];
int calc(double angle)
{
int r=0, ret=0;
for(int l=0; l<n-1; l++)
{
int eql=0;
while(sgn(ang[l+eql]-ang[l])==0) eql++;
l=l+eql-1;
r=max(r, l+1);
while(r-l+1<=n-1&&sgn(ang[r]-ang[l] - angle) < 0) r++;
ret += (r-l-1)*eql;
}
return ret;
}
void solve()
{
LL ans1=0, ans2=0;
for(int i=0; i<n; i++) cin>>p[i].x>>p[i].y;
for(int i=0; i<n; i++)
{
node tmp;
for(int j=i+1; j<i+n; j++)
{
int id=j%n;
tmp=p[id]-p[i];
ang[j-i-1]=atan2(tmp.y, tmp.x);
}
sort(ang, ang+n-1);
for(int j=0; j<n-1; j++) ang[j+n-1]=ang[j]+2*pi;
int ret=calc(pi*0.5);
ans1+=ret;
ans2+=calc(pi)-ret;
}
printf("%I64d\n", (ans1-2*ans2)/3);
}
int main()
{
while(cin>>n)
{
solve();
}
return 0;
}