LA 4064 Magnetic Train Tracks
题目大意:
在平面上给n个点(任意三点不共线),问这些点共组成了多少锐角或者直角三角形.
(
1≤n≤1200
)
题目分析:
锐角三角形必须满足三个角都为锐角,并不利于统计.尝试统计不是锐角或者直角三角形,即——统计钝角三角形的个数.
统计钝角三角形只需要找到钝角即可,且钝角三角形仅有一个钝角,不会出现重复的情况.
如何统计钝角三角形?
选择极角排序,尝试固定一个中心点,计算出其他所有点与该点形成的极角,排序.
若再确定一个选取点,那么只要是其他能与中心点和选取点构成钝角的三角形皆为钝角三角形.
如上图所示,确定了中心点和选取点后,在B区域内的点可构成钝角三角形.
因为排序之后的极角是单调递增的,所以只需要一次扫描过去即可统计某一中心点形成的所有钝角三角形.
(但是好像本题必须要加eps,不然会WA)
代码:
#include<cmath>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const double eps=1e-10;
const double PI=acos(-1);
const int maxn=1200+5;
int x[maxn],y[maxn],n;
double de[maxn*2];
int count(int c)
{
int cnt=0;
for(int i=0;i<n;i++) if(i!=c)
de[cnt++]=atan2(y[i]-y[c],x[i]-x[c]);
sort(de,de+n-1);
for(int i=0;i<n-1;i++) de[i+n-1]=de[i]+2*PI;
int pos1=0,pos2=0,ret=0;
for(int i=0;i<n-1;i++) {
while(de[pos1]-de[i]+eps<=PI/2) ++pos1;//这里若不加eps,会WA掉
while(de[pos2]-de[i]<PI) ++pos2;
ret+=pos2-pos1;
}
return ret;
}
int solve()
{
if(n<3) return 0;
int tot=0;
for(int i=0;i<n;i++) tot+=count(i);
return n*(n-1)*(n-2)/6-tot;
}
int main()
{
int kase=0;
while(scanf("%d",&n)==1&&n) {
for(int i=0;i<n;i++) scanf("%d%d",&x[i],&y[i]);
printf("Scenario %d:\nThere are %d sites for making valid tracks\n",++kase,solve());
}
return 0;
}