zoukankan      html  css  js  c++  java
  • 极角排序+求锐角三角形个数——uva12123

    这个版本还不能处理三点共线的情况(处理起来其实比较麻烦)

    可以用atan2来排序(较为简单,但是精度误差大),也可以用叉积排序(比较优秀)

    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:
    " , cas++);
            printf("There are %lld sites for making valid tracks
    " , ans);
        }
        return 0;
    }

    叉积

    /*
    极角排序:定义极角大小顺序是3412象限 
    求锐角三角形个数/总面积(可能三点共线)
        总三角形-直角三角形-钝角三角形=C(n,3)-直角个数-钝角个数
        以每个点为源点,级角排序,然后双指针扫一次求直角钝角个数
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define N 4005
    typedef double db;
    const db eps=1e-6;
    const db pi=acos(-1);
    int sign(db k){if (k>eps) return 1; 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++){
                    //p1的夹角[0,pi/2) 
                    while(p1+1<j+tot && sign(cross(pp[j],pp[p1+1]))>=0 && sign(dot(pp[j],pp[p1+1]))>0)
                        p1++;
                    //p2的夹角[0,pi] 
                    while(p2+1<j+tot && sign(cross(pp[j],pp[p2+1]))>=0)
                        p2++;
                    sum+=p2-p1;
                }
            }
            printf("Scenario %d:
    ",tt);
            printf("There are %d sites for making valid tracks
    ",ans-sum);
        }
    }
    /*
    6
    26 23
    51 94
    103 110
    164 107
    116 67
    73 16
    */
  • 相关阅读:
    September 17th 2016 Week 38th Saturday
    【2016-09-16】UbuntuServer14.04或更高版本安装问题记录
    September 16th 2016 Week 38th Friday
    September 11th 2016 Week 38th Sunday
    September 12th 2016 Week 38th Monday
    September 10th 2016 Week 37th Saturday
    September 9th 2016 Week 37th Friday
    c++暂停
    八皇后问题
    ( 转转)Android初级开发第九讲--Intent最全用法(打开文件跳转页面等)
  • 原文地址:https://www.cnblogs.com/zsben991126/p/12333633.html
Copyright © 2011-2022 走看看