[HDU 5784] How Many Triangles (几何+极角排序)

HDU - 5784

几何题,给定平面上若干个不重复的点,
求这些点能组成多少个锐角三角形


我刚开始的时候想的是枚举钝角和直角
然后计算每三个点能组成的三角形的个数
减去共线的,再减去钝角和直角的个数,即为答案
而且我在极角排序之后,我试图用二分来确定上下界
这样也不是不能做,但是比较麻烦

题解的方法就比较好
统计锐角的个数,设为 A ,钝角和直角的个数,设为 B
每个锐角三角形有三个锐角,每个钝角和直角三角形均贡献两个锐角
所以答案即为 A2B3
然后题解在对每个点极角排序之后,采用 two pointers的方式来找上下界
比二分好写多了,也很方便,时间复杂度 (N2logN)

统计锐角个数的时候,要考虑和当前枚举的点共线的那些点
顺便精度要开得小一些,要开到 1e-10以上
顺便感谢某周教我如何判精度,输出最小角的atan2
比如这题就是 atan2(1,1e9) = 1e-9,然后大两个级别的精度就行

#pragma comment(linker, "/STACK:102400000,102400000")
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef pair<int,int> Pii;
typedef long long LL;
typedef unsigned long long ULL;
typedef double DBL;
typedef long double LDBL;
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) MST(a,0)
#define SQR(a) ((a)*(a))
#define PCUT puts("----------")

const DBL eps=1e-12, PI=acos(-1.0);
const int maxn=2e3+10;
int sgn(DBL x){return x>eps?1:(x<-eps?(-1):0);}
struct Vector
{
    DBL x,y;
    Vector operator - (const Vector &v) const {return {x-v.x, y-v.y};}
    DBL operator * (const Vector &v) const {return x*v.x + y*v.y;}
    int read() {return scanf("%lf%lf", &x, &y);}
};
typedef Vector Point;

int N;
Point P[maxn];
DBL ang[2*maxn];

int Cnt(DBL);

int main()
{
    #ifdef LOCAL
    freopen("in.txt", "r", stdin);
//  freopen("out.txt", "w", stdout);
    #endif
    printf("%.12f\n", atan2(1,1e9));
    while(~scanf("%d", &N))
    {
        for(int i=0; i0, nans=0;
        for(int i=0; ifor(int j=i+1; jint id=j%N;
                L = P[id]-P[i];
                ang[j-i-1] = atan2(L.y, L.x);
            }
            sort(ang, ang+N-1);
            memcpy(ang+N-1, ang, sizeof(DBL)*(N-1));
            for(int j=N-1; j<2*N-2; j++) ang[j] += 2.0*PI;
            int res = Cnt(PI*0.5);
            ans += res;
            nans += Cnt(PI) - res;
        }
        printf("%lld\n", (ans-2*nans)/3);
    }
    return 0;
}

int Cnt(DBL A)
{
    int r=0, res=0;
    for(int l=0; l1; l++)
    {
        int ecnt=0;
        while( sgn(ang[l+ecnt]-ang[l]) == 0) ecnt++;
        l = l+ecnt-1;
        r = max(r, l+1);
        while( r-l+1 <= N-1 && sgn(ang[r]-ang[l] - A) < 0) r++;
        res += (r-l-1)*ecnt;
    }
    return res;
}

你可能感兴趣的:(几何)