Hdu 5784 How Many Triangles(极角排序+尺取法)

来源:互联网 发布:midas civil软件下载 编辑:程序博客网 时间:2024/05/16 15:07

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=5784

思路:

1.锐角三角形总锐角个数=总锐角数-非锐角三角形提供锐角数。则锐角三角形个数=总锐角数/3(即(锐角数-2*(直角+钝角数))/3,每钝角和直角三角形提供两锐角)。

2.枚举每个点p[i],以p[i]为原点,求其他n-1个点与原点组成的向量,按极角(小于0时加2*PI)递增排序。设置三个指针l、r、equ,分别代表第一个直角、第一个平角、第一个非0角的位置。枚举n-1个向量j,由于极角递增,两向量角度即为极角l-极角j,l、r、equ递增则形成的角度也递增(相当于尺取法)。则以点p[i]为顶点的锐角个数为l-equ(所有小于90度的角减去0度的角),钝角个数为r-l(所有小于180度的角减去小于等于90度的角)。

3.当指针l、r、equ旋转一周时(l、r、equ下标超过n-1,但此时所有角度尚未枚举完毕),为了便于求角度(即最后一部分向量与起始部分向量所成角度),枚举之前将所有极角加2*PI复制一遍。

#include<cmath>#include<cstdio>#include<vector>#include<cstring>#include<iostream>#include<algorithm>#define debugusing namespace std;const double eps=1e-11;const double PI=acos(-1.0);const int maxn=4000+50;int n;struct Point{    double x,y;    Point() {}    Point(double x,double y):x(x),y(y) {}    void read()    {        scanf("%lf%lf",&x,&y);    }};typedef Point Vector;Vector operator - (Vector A,Vector B){    return Vector(A.x-B.x,A.y-B.y);}int dcmp(double x){    if(fabs(x)<eps) return 0;    else return x<0?-1:1;}int cnt;Point p[maxn];double a[maxn];int main(){#ifdef debu    freopen("in.txt","r",stdin);#endif // debug    while(scanf("%d",&n)!=EOF)    {        int acute=0,notacute=0;        for(int i=1; i<=n; i++) p[i].read();        for(int i=1; i<=n; i++)        {            cnt=0;            for(int j=1; j<=n; j++)            {                if(i==j)continue;                Vector tmp=p[j]-p[i];                double ang=atan2(tmp.y,tmp.x);                if(ang<0) ang+=2*PI;                a[++cnt]=ang;            }            sort(a+1,a+cnt+1);            for(int j=1;j<=cnt;j++) a[cnt+j]=a[j]+2*PI;            int l=1,r=1,equ=1;            for(int j=1; j<=cnt; j++)            {                while(l<=2*cnt&&dcmp(a[l]-a[j]-PI/2)<0) l++;                while(r<=2*cnt&&dcmp(a[r]-a[j]-PI)<0) r++;                while(equ<=2*cnt&&dcmp(a[equ]-a[j])==0) equ++;                acute+=l-equ;                notacute+=r-l;            }        }        printf("%d\n",(acute-2*notacute)/3);    }    return 0;}




原创粉丝点击