This version also does not handle the case of collinear (in fact, too much trouble dealing with them)
Atan2 can be ordered (simple, but large accuracy error), can also be used to sort the cross product (relatively good)
atan2
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <cstdlib> using namespace std; typedef long long LL; const int maxn = 1250; const double pi = acos(-1.0); const double eps = 1e-10; struct point{ double x,y; }p[maxn]; double s[maxn*2]; int main() { //freopen("input.txt" , "r" , stdin); int N , cas = 1; while(scanf("%d" ,&N)!=EOF && N){ for(int i=0;i<N;i++) scanf("%lf%lf" , &p[i].x , &p[i].y); LL obtuse = 0; for(int i=0;i<N;i++){ if(i) swap(p[i] , p[0]); for(int k=1;k<N;k++) s[k] = atan2(p[k].y-p[0].y , p[k].x-p[0].x); sort(s+1 , s+N); for(int k=1;k<N;k++) s[k+N-1] = s[k] + 2*pi; int k=1 , e1=1 , e2=1; for(; k<N; k++){ while(s[e1] - s[k] - 0.5*pi < -eps) e1++; while(s[e2] - s[k] <= pi) e2++; obtuse += e2 - e1; } } LL ans = N*(N-1)*(N-2)/6 - obtuse; printf("Scenario %d:\n" , cas++); printf("There are %lld sites for making valid tracks\n" , ans); } return 0; }
Cross product
/ * Polar angle Sort: define a polar angle of the order of 3412 quadrant is seeking an acute triangle number / total area (possibly three collinear) Total triangle - right triangle - obtuse triangle = C (n, 3) - the number of right angles - obtuse The number in each source point, angle sorting stage, then the number of double pointer sweep seeking a right angle to an obtuse angle * / #include <bits / STDC ++ H.> the using namespace STD; #define N 4005 typedef double DB; const DB EPS 1E-= . 6 ; const DB PI = ACOS (- . 1 ); int Sign (K DB) { IF (K> EPS) return . 1 ; the else IF (K <-EPS) return - . 1 ; return 0 ;} int cmp(db k1,db k2){return sign(k1-k2);} struct point{ db x,y; point(){} point(db x,db y):x(x),y(y){} point operator + (const point &k1) const{return (point){k1.x+x,k1.y+y};} point operator - (const point &k1) const{return (point){x-k1.x,y-k1.y};} point operator * (db k1) const{return (point){x*k1,y*k1};} point operator / (db k1) const{return (point){x/k1,y/k1};} int getP() const{return sign(y)==1||(sign(y)==0&&sign(x)>=0);} }; db cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;} db dot(point k1,point k2){return k1.x*k2.x+k1.y*k2.y;} db rad(point k1,point k2){return atan2(cross(k1,k2),dot(k1,k2));} int comp(point k1,point k2){ if(k1.getP()==k2.getP())return sign(cross(k1,k2))>0; return k1.getP()<k2.getP(); } int n,ans; point pp[N],p[N],O; int main(){ int tt=0; while(cin>>n && n){ ++tt; for(int i=1;i<=n;i++) scanf("%lf%lf",&p[i].x,&p[i].y); ans=n*(n-1)*(n-2)/6; long long sum=0; for(int i=1;i<=n;i++){ O=p[i]; int tot=0; for(int j=1;j<=n;j++) if(j!=i)pp[++tot]=p[j]-O; sort(pp+1,pp+1+tot,comp); for(int j=1;j<=tot;j++) pp[j+tot]=pp[j]; int p1=1,p2=1; For ( int J = . 1 ; J <= TOT; J ++ ) { // angle p1 of [0, PI / 2) the while (p1 + . 1 <J + TOT && Sign (Cross (PP [J], PP [p1 + . 1 ]))> = 0 && Sign (DOT (PP [J], PP [P1 + . 1 ]))> 0 ) P1 ++ ; // angle p2, [0, PI] the while (p2 + . 1 <J + TOT Sign && (Cross (PP [J], PP [P2 + . 1 ]))> = 0 ) P2 ++ ; SUM + = P2- P1; } } printf("Scenario %d:\n",tt); printf("There are %d sites for making valid tracks\n",ans-sum); } } /* 6 26 23 51 94 103 110 164 107 116 67 73 16 */