• [计算几何]补题


    3____计算几何

    Triangle

    
    

    Naive and Silly Muggles

    
    

    3.1____叉积判断点线关系

    TOYS

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    
    int n,m,x1,x2,y1,y2;
    /// n为分区数,m为玩具数,左上坐标,右下坐标
    
    struct Point
    {
        int x,y;
    };
    
    //typedef Point Vector;
    //Vector oprator + ( Vector A,Vector B ) { return Vector ( A.x + B.x , A.y + B.y ); }
    //Vector oprator - ( Vector A,Vector B ) { return Vector (  )}
    
    struct Line
    {
        Point a,b;
    }line[5001];
    
    int cnt[5001];
    
    inline int Cross(Point p1,Point p2) ///求叉积
    {
        return p1.x * p2.y - p1.y * p2.x;
    }
    
    inline bool dir(int k ,Point p)
    {
        Point a,b;
        a.x = line[k].a.x - p.x;
        a.y = line[k].a.y - p.y;
        b.x = line[k].b.x - p.x;
        b.y = line[k].b.y - p.y;
        return Cross( a,b ) > 0;
    }
    
    inline int Find(Point p)
    {
        int l = 1, r = n ;
        while( l <= r )
        {
            int mid = ( l + r) >> 1;
            if( dir(mid,p) ) l = mid + 1;
            else r = mid - 1;
        }
        return r;
    }
    
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
    
        while( cin >> n )
        {
            if( n == 0) break;
            memset(cnt,0,sizeof cnt);
            cin >> m >> x1 >> y1 >> x2 >> y2;
    
            for(int i = 1; i <= n ; i++)
            {
                line[i].a.y = y1;
                line[i].b.y = y2;
                cin >> line[i].a.x >> line[i].b.x;
            }
    
            ///对应区间
            for(int i = 1; i <= m ; i++)
            {
                Point p;
                cin >> p.x >> p.y;
                ++cnt[ Find(p) ];
            }
            ///打印
            for(int i = 0 ; i <= n ;i ++) cout << i <<": " << cnt[i] <<endl;
            cout<< endl;
    
        }
    
        return 0;
    }
    

    Segments

    #include <cstdio>
    #include <iostream>
    #include <cmath>
    #include <cstring>
    using namespace std;
    
    const int N = 105;
    const double eps = 1e-8;
    
    int sgn(double x)
    {
        if( fabs(x) < eps ) return 0;
        if( x < 0 ) return -1;
        else return 1;
    }
    ///square of a double
    inline double sqr(double x) { return x * x; }
    
    struct Point
    {
        double x,y;
        Point(){}               ///no arguments constructor
        Point(double _x,double _y) {
            x = _x , y = _y;    ///arguments constructor
        }
        bool operator == (Point b) const{
            return sgn(x - b.x) == 0 && sgn(y - b.y) == 0;
        }
        bool operator < (Point b) const{
            return sgn(x - b.x) == 0? sgn(y - b.y) < 0 : x < b.x;
        }
        double operator ^ (const Point &b) const{
            return x * b.y - y * b.x;
        }
         Point operator - (const Point &b) const{
            return Point(x - b.x , y - b.y);
        }
        Point operator + (const Point &b) const{
            return Point(x + b.x , y + b.y);
        }
    }s[N*2];
    
    struct Line
    {
        Point s,e;
        Line(){}
        Line( Point _s, Point _e ){ s =_s ; e=_e; }
    
        ///直线与线段相交判断
        ///-*this line -v seg
        ///2规范相交,1非规范相交,0不相交
        bool linecrossseg(Line v){
            return sgn( (v.s - e) ^ (s - e) ) * sgn(( v.e-e ) ^ (s -e) ) <= 0;
        }
    
    }line[N];
    
    int main()
    {
    
        ios::sync_with_stdio(false);
        cin.tie(0);
    
        int t;
        cin >> t;
        while(t--)
        {
            int n,x1,x2,y1,y2;
            cin >> n;
            for(int i = 1 ; i <= n ; i++)
            {
                cin >> line[i].s.x >> line[i].s.y;
                cin >> line[i].e.x >> line[i].e.y;
                s[i*2 -1] = line[i].s , s[i*2] = line[i].e;
            }
    
            bool flag = 0;
            ///对每个点进行枚举
            for(int i = 1; i <= 2 * n ; i++)
            {
                if(flag) break;
                for(int j = i + 1 ; j <= 2 * n ; j++)
                {
                    //cout << s[i].x << ' ' << s[i].y << " | " <<s[j].x << ' '<< s[j].y <<endl;
                    Line te(s[i],s[j]);
                    if( s[i].x == s[j].x && s[i].y == s[j].y ) continue;
                    ///验证这个枚举的线是不是与每个线段都相交
                    int k;
                    for(k = 1;k <= n; k++)
                    //cout << te.linecrossseg( line[k] ) << endl;
                    if( !te.linecrossseg( line[k] ) ) break;
                    if(k == n +1) flag = 1;
                    //cout << k << endl;
                }
            }
            if(flag) cout << "Yes!" <<endl;
            else cout << "No!" << endl;
           // cout<< endl;
    
        }
    
        return 0;
    }
    

    3.2____多边形重心

    Lifting the Stone

    #include <bits/stdc++.h>
    using namespace std;
    const double eps = 1e-8;
    const double pi = acos( -1.0);
    
    ///Compares a double to zero
    int sgn(double x)
    {
        if( fabs(x) < eps ) return 0;
        if( x < 0 ) return -1;
        else return 1;
    }
    ///square of a double
    inline double sqr(double x) { return x * x; }
    /////////////////////////////////////////////////
    struct Point
    {
        double x,y;
        Point(){}               ///no arguments constructor
        Point(double _x,double _y) {
            x = _x , y = _y;    ///arguments constructor
        }
        bool operator == (Point b) const{
            return sgn(x - b.x) == 0 && sgn(y - b.y) == 0;
        }
        bool operator < (Point b) const{
            return sgn(x - b.x) == 0? sgn(y - b.y) < 0 : x < b.x;
        }
        ///数量积
        Point operator - (const Point &b) const{
            return Point(x - b.x , y - b.y);
        }
        Point operator + (const Point &b) const{
            return Point(x + b.x , y + b.y);
        }
        Point operator * (const double &k) const{
            return Point(x * k , y * k );
        }
        Point operator / (const double &k) const{
            return Point(x / k , y / k);
        }
        ///叉积
        double operator ^ (const Point &b) const{
            return x * b.y - y * b.x;
        }
        ///点积
        double operator * (const Point &b) const{
            return x * b.x + y * b.y;
        }
        ///线段的长度
        double len(){
            return hypot(x,y);  ///<cmath>
        }
        ///长度的平方
        double len2(){
            return x * x + y * y;
        }
        ///返回两点的距离
        double distance(Point p){
            return hypot( x - p.x , y - p.y );
        }
    
    };
    
    const int maxp = 10000010;
    
    struct polygon
    {
        int n;
        Point p[maxp];
        //Line l[maxp];
    
        double getarea()
        {
            double sum = 0;
            for(int i = 0; i<n ; i++){
                sum += p[i].distance(p[(i+1)%n]);
            }
            return sum;
        }
    
        Point getbarycentre()
        {
            Point ret(0,0);
            double area = 0;
            for(int i = 1; i < n - 1;  i++){
                double tmp = (p[i] - p[0] )^ ( p[i +1] -p[0] );
               // printf("%.2f
    ",tmp);
                if(sgn(tmp) == 0)continue;
                area += tmp;
                ret.x += ( p[0].x + p[i].x + p[i +1].x )/ 3 * tmp;
                ret.y += ( p[0].y + p[i].y + p[i+1].y ) /3 * tmp;
            }
            if( sgn(area) ) ret = ret /area;
            return ret;
        }
    
    }pol;
    
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
    
        int t;
        scanf("%d",&t);
        while(t--)
        {
            int n;
            scanf("%d",&n);
            pol.n = n ;
            //scanf("%d%d",&pol.p[0].x,&pol.p[0].y);
            for(int i = 0; i < n ; i++)
            {
                scanf("%lf %lf",&pol.p[i].x,&pol.p[i].y);
    //            pol.l[i-1].s.x = pol.p[i-1].x;
    //            pol.l[i-1].s.y = pol.p[i-1].y;
    //            pol.l[i-1].e.x = pol.p[i].x;
    //            pol.l[i-1].e.y = pol.p[i].y;
            }
    
            Point ans = pol.getbarycentre();
            if( ans.x > -0.001 && ans.x < 0.0 ) ans.x = 0;
            if( ans.y > -0.001 && ans.y < 0.0 ) ans.y = 0;
            printf("%.2f %.2f
    ",ans.x ,ans.y);
    
        }
    
        return 0;
    }
    

    3.3____极角排序

    思路 :事先将两个点连成线,然后用叉积来判断第三个点在这个线的左边还是右边,

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    #include <math.h>
    using namespace std;
    
    const double eps = 1e-8;
    const double pi = acos( -1.0);
    
    ///Compares a double to zero
    int sgn(double x)
    {
        if( fabs(x) < eps ) return 0;
        if( x < 0 ) return -1;
        else return 1;
    }
    ///square of a double
    inline double sqr(double x) { return x * x; }
    
    struct Point
    {
        double x,y;
        int num;
    
        Point(){}               ///no arguments constructor
        Point(double _x,double _y) {
            x = _x , y = _y;    ///arguments constructor
        }
        bool operator == (Point b) const{
            return sgn(x - b.x) == 0 && sgn(y - b.y) == 0;
        }
        bool operator < (Point b) const{
            return sgn(x - b.x) == 0? sgn(y - b.y) < 0 : x < b.x;
        }
        ///数量积
        Point operator - (const Point &b) const{
            return Point(x - b.x , y - b.y);
        }
        Point operator + (const Point &b) const{
            return Point(x + b.x , y + b.y);
        }
        Point operator * (const double &k) const{
            return Point(x * k , y * k );
        }
        Point operator / (const double &k) const{
            return Point(x / k , y / k);
        }
        ///叉积
        double operator ^ (const Point &b) const{
            return x * b.y - y * b.x;
        }
        ///点积
        double operator * (const Point &b) const{
            return x * b.x + y * b.y;
        }
        ///返回两点的距离
        double distance(Point p){
            return sqrt( sqr( x- p.x ) + sqr(y - p.y) );
        }
    }P[510];
    
    Point ans[510];
    
    Point init;
    
    bool cmp(Point a,Point b)
    {
        if( fabs( (a - init)^( b - init ) ) < eps ) ///  如果极角相同,比较距离
        {
            return init.distance(a) < init.distance(b);
        }
        else return ( (a - init) ^ (b - init) )> 0;
    }
    
    int main()
    {
        ios::sync_with_stdio( false);
        cin.tie(0);
    
        int n,t;
        cin >> t;
        while(t--)
        {
            cin >> n;
            int miny = 100000000;
            for(int i = 1 ; i <= n ; i++){
                cin >> P[i].num >> P[i].x >> P[i].y;
                if( P[i].y < miny ) miny = P[i].y;
            }
    
            init.x = 0,init.y = miny;
    
            for(int i = 1 ; i <= n ; i++)
            {
                sort(P+i,P+1+n,cmp);
                ans[i] = P[i];
                init = P[i];
            }
    
            cout << n << ' ';
            for(int i = 1; i <= n ; i++ )
                cout << ans[i].num << ' ';
    
            cout <<endl;
        }
    
        return 0;
    }
    

    3.4____计算几何,思维题

    An Easy Problem?!

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <vector>
    using namespace std;
    
    const double eps = 1e-8;
    const double pi = acos( -1.0);
    
    ///Compares a double to zero
    int sgn(double x)
    {
        if( fabs(x) < eps ) return 0;
        if( x < 0 ) return -1;
        else return 1;
    }
    ///square of a double
    inline double sqr(double x) { return x * x; }
    /////////////////////////////////////////////////
    struct Point
    {
        double x,y;
        Point(){}               ///no arguments constructor
        Point(double _x,double _y) {
            x = _x , y = _y;    ///arguments constructor
        }
    
        bool operator == (Point b) const{
            return sgn(x - b.x) == 0 && sgn(y - b.y) == 0;
        }
        bool operator < (Point b) const{
            return sgn(x - b.x) == 0? sgn(y - b.y) < 0 : x < b.x;
        }
        ///数量积
        Point operator - (const Point &b) const{
            return Point(x - b.x , y - b.y);
        }
        Point operator + (const Point &b) const{
            return Point(x + b.x , y + b.y);
        }
        Point operator * (const double &k) const{
            return Point(x * k , y * k );
        }
        Point operator / (const double &k) const{
            return Point(x / k , y / k);
        }
        ///叉积
        double operator ^ (const Point &b) const{
            return x * b.y - y * b.x;
        }
        ///点积
        double operator * (const Point &b) const{
            return x * b.x + y * b.y;
        }
        ///线段的长度
        double len(){
            return hypot(x,y);  ///<cmath>
        }
        ///长度的平方
        double len2(){
            return x * x + y * y;
        }
        ///返回两点的距离
        double distance(Point p){
            return hypot( x - p.x , y - p.y );
        }
    };
    
    struct Line
    {
    
        vector<char> croset;
    
        char name;
    
        Point s,e;
        Line(){}
        Line( Point _s, Point _e ){ s =_s ; e=_e; }
    
        void input(Point _p1,Point _p2)
        {
            s = _p1,e = _p2;
        }
    
        ///直线与线段相交判断
        ///-*this line -v seg
        ///2规范相交,1非规范相交,0不相交
        bool linecrossseg(Line v){
            return sgn( (v.s - e) ^ (s - e) ) * sgn(( v.e-e ) ^ (s -e) ) <= 0;
        }
    		///点与直线关系
        ///1在左侧
        ///2在右侧
        ///3在直线
        int relation(Point p){
            int c = sgn( (p-s) ^ (e -s) );
            if(c < 0) return 1;
            else if(c > 0) return 2;
            else return 3;
        }
        ///点在线段上的判断
        bool point_on_seg(Point p){
            return sgn((p-s)^(e-s) ) == 0 && sgn( (p-s)*(p-e) ) <= 0 ;
        }
        ///两向量平行(对应直线平行或重合)
        bool parallel(Line v){
            return sgn( (e-s)^( v.e - v.s ) ) == 0;
        }
        ///两直线关系 0-平行,1-重合,2-相交
        int linecrossline(Line v){
            if( (*this).parallel(v) )
                return v.relation(s) == 3;
            return 2;
        }
        ///得到交点,需先判断直线是否相交
        Point crosspoint(Line v){
            double a1 = ( v.e - v.s ) ^ ( s - v.s );
            double a2 = ( v.e - v.s ) ^ ( e - v.s );
            return Point( (s.x * a2 - e.x * a1)/(a2 - a1) , (s.y *a2 - e.y *a1)/(a2 - a1));
        }
    
        ///两线段相交判断
        ///2 规范相交
        ///1 非规范相交
        ///0 不想交
        int segcrossseg(Line v) {
            int d1 = sgn((e - s) ^ (v.s - s));
            int d2 = sgn((e - s) ^ (v.e - s));
            int d3 = sgn((v.e - v.s) ^ (s - v.s));
            int d4 = sgn((v.e - v.s) ^ (e - v.s));
            if ((d1 ^ d2) == -2 && (d3 ^ d4) == -2)return 2;
            return (d1 == 0 && sgn((v.s - s) * (v.s - e)) <= 0) ||
                (d2 == 0 && sgn((v.e - s) * (v.e - e)) <= 0) ||
                (d3 == 0 && sgn((s - v.s) * (s - v.e)) <= 0) ||
                (d4 == 0 && sgn((e - v.s) * (e - v.e)) <= 0);
        }
    
    };
    
    
    struct polygon
    {
        int num;      ///点的数量
        Point p[4];
        Line l[4];
    
    
        struct cmp{
            Point p;
            cmp(const Point &p0){ p = p0;}
            bool operator()( const Point &aa ,const Point &bb){
                Point a = aa,b = bb;
                int d = sgn( (a-p)^(b-p) );
                if(d == 0)  return sgn( a.distance(p) - b.distance(p)) < 0;
                return d > 0;
            }
        };
    
        /// 3在顶点上
        /// 2在边上
        /// 1在内部
        /// 0在外面
        int Point_in_polygon(Point tep)
        {
            for(int i = 0 ; i < num ; i++){
                if( p[i] == tep ) return 3;
            }
            for(int i = 0 ; i < num ; i++){
                if( l[i].point_on_seg(tep) ) return 2;
            }
            int tecnt = 0;
            for(int i = 0 ; i < num ; i++)
            {
                int j = (i + 1) % num;
                int c = sgn( (tep - p[j]) ^ (p[i] - p[j]) );
                int u = sgn( p[i].y - tep.y );
                int v = sgn( p[j].y - tep.y );
                if( c > 0 && u < 0 && v >=0 ) tecnt ++;
                if( c < 0 && u >= 0 && v < 0 ) tecnt --;
            }
            return tecnt != 0;
        }
    
    }pol;
    
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
    
        int t,n;
        cin >> t;
    
        while(t--)
        {
            Point p1,p2,j1,j3;
            cin >> p1.x >> p1.y >> p2.x >> p2.y >> j1.x >> j1.y >> j3.x >> j3.y;
            if( j1.x > j3.x ) swap(j1,j3);
    
            Line lp(p1,p2);
            Point j2,j4;
            j2.x = j3.x,j2.y = j1.y,j4.x = j1.x ,j4.y = j3.y;
            polygon pol;
            pol.p[0] = j1;
            pol.p[1] = j2;
            pol.p[2] = j3;
            pol.p[3] = j4;
            pol.l[0].input(j1,j2);pol.l[1].input(j2,j3),pol.l[2].input(j3,j4),pol.l[3].input(j4,j1);
            pol.num = 4;
            bool flag = 0;
            for(int i = 0; i < 4 ; i++)
                if( lp.segcrossseg(pol.l[i]) > 0 ){
                    flag = 1;
                    break;
                }
    
    
            if( flag ) cout <<'T' <<endl;
            else{
                    //cout << pol.Point_in_polygon(p1) << ' ' <<  pol.Point_in_polygon(p2) << endl;
                if( pol.Point_in_polygon(p1) && pol.Point_in_polygon(p2)  ) cout << 'T' << endl;
                else cout << 'F' <<endl;
            }
    
    
        }
    
    
    
        return 0;
    }
    

    Kadj Squares

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    
    using namespace std;
    
    struct node
    {
        int l,r,s;
    }p[500];
    
    int loc[500];
    
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
    
        int n;
        while(cin >> n)
        {
            if( n == 0) break;
            for(int i = 0 ;  i < n ; i++)   cin >> p[i].s;
    
            for(int i = 0 ; i < n  ; i ++)
            {
                int ll = 0;
                for(int j = 0; j < i ; j ++)
                    ll = max(ll , p[j].r - abs( p[j].s - p[i].s ));
                p[i].l =ll;
                p[i].r = ll + 2 * p[i].s;
            }
    
            for(int i =  0 ; i < n ; i++)
            {
                int ml = p[i].l,mr = p[i].r;///重要
                for(int j = 0; j < i ; j++)
                        ml = max(ml,p[j].r);
    
                for(int j = i + 1; j < n ; j++)
                        mr = min(mr,p[j].l);
    
                if( ml >= mr ) continue;
                else cout << i + 1 << ' ';
            }
            cout << endl;
        }
    
    
        return 0;
    }
    
    

    3.5____线段与多边形判断相交

    Intersection

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <vector>
    using namespace std;
    
    const double eps = 1e-8;
    const double pi = acos( -1.0);
    
    ///Compares a double to zero
    int sgn(double x)
    {
        if( fabs(x) < eps ) return 0;
        if( x < 0 ) return -1;
        else return 1;
    }
    ///square of a double
    inline double sqr(double x) { return x * x; }
    /////////////////////////////////////////////////
    struct Point
    {
        double x,y;
        Point(){}               ///no arguments constructor
        Point(double _x,double _y) {
            x = _x , y = _y;    ///arguments constructor
        }
    
        bool operator == (Point b) const{
            return sgn(x - b.x) == 0 && sgn(y - b.y) == 0;
        }
        bool operator < (Point b) const{
            return sgn(x - b.x) == 0? sgn(y - b.y) < 0 : x < b.x;
        }
        ///数量积
        Point operator - (const Point &b) const{
            return Point(x - b.x , y - b.y);
        }
        Point operator + (const Point &b) const{
            return Point(x + b.x , y + b.y);
        }
        Point operator * (const double &k) const{
            return Point(x * k , y * k );
        }
        Point operator / (const double &k) const{
            return Point(x / k , y / k);
        }
        ///叉积
        double operator ^ (const Point &b) const{
            return x * b.y - y * b.x;
        }
        ///点积
        double operator * (const Point &b) const{
            return x * b.x + y * b.y;
        }
        ///线段的长度
        double len(){
            return hypot(x,y);  ///<cmath>
        }
        ///长度的平方
        double len2(){
            return x * x + y * y;
        }
        ///返回两点的距离
        double distance(Point p){
            return hypot( x - p.x , y - p.y );
        }
    };
    
    struct Line
    {
    
        vector<char> croset;
    
        char name;
    
        Point s,e;
        Line(){}
        Line( Point _s, Point _e ){ s =_s ; e=_e; }
    
        void input(Point _p1,Point _p2)
        {
            s = _p1,e = _p2;
        }
    
        ///直线与线段相交判断
        ///-*this line -v seg
        ///2规范相交,1非规范相交,0不相交
        bool linecrossseg(Line v){
            return sgn( (v.s - e) ^ (s - e) ) * sgn(( v.e-e ) ^ (s -e) ) <= 0;
        }
    		///点与直线关系
        ///1在左侧
        ///2在右侧
        ///3在直线
        int relation(Point p){
            int c = sgn( (p-s) ^ (e -s) );
            if(c < 0) return 1;
            else if(c > 0) return 2;
            else return 3;
        }
        ///点在线段上的判断
        bool point_on_seg(Point p){
            return sgn((p-s)^(e-s) ) == 0 && sgn( (p-s)*(p-e) ) <= 0 ;
        }
        ///两向量平行(对应直线平行或重合)
        bool parallel(Line v){
            return sgn( (e-s)^( v.e - v.s ) ) == 0;
        }
        ///两直线关系 0-平行,1-重合,2-相交
        int linecrossline(Line v){
            if( (*this).parallel(v) )
                return v.relation(s) == 3;
            return 2;
        }
        ///得到交点,需先判断直线是否相交
        Point crosspoint(Line v){
            double a1 = ( v.e - v.s ) ^ ( s - v.s );
            double a2 = ( v.e - v.s ) ^ ( e - v.s );
            return Point( (s.x * a2 - e.x * a1)/(a2 - a1) , (s.y *a2 - e.y *a1)/(a2 - a1));
        }
    
        ///两线段相交判断
        ///2 规范相交
        ///1 非规范相交
        ///0 不想交
        int segcrossseg(Line v) {
            int d1 = sgn((e - s) ^ (v.s - s));
            int d2 = sgn((e - s) ^ (v.e - s));
            int d3 = sgn((v.e - v.s) ^ (s - v.s));
            int d4 = sgn((v.e - v.s) ^ (e - v.s));
            if ((d1 ^ d2) == -2 && (d3 ^ d4) == -2)return 2;
            return (d1 == 0 && sgn((v.s - s) * (v.s - e)) <= 0) ||
                (d2 == 0 && sgn((v.e - s) * (v.e - e)) <= 0) ||
                (d3 == 0 && sgn((s - v.s) * (s - v.e)) <= 0) ||
                (d4 == 0 && sgn((e - v.s) * (e - v.e)) <= 0);
        }
    
    };
    
    
    struct polygon
    {
        int num;      ///点的数量
        Point p[4];
        Line l[4];
    
    
        struct cmp{
            Point p;
            cmp(const Point &p0){ p = p0;}
            bool operator()( const Point &aa ,const Point &bb){
                Point a = aa,b = bb;
                int d = sgn( (a-p)^(b-p) );
                if(d == 0)  return sgn( a.distance(p) - b.distance(p)) < 0;
                return d > 0;
            }
        };
    
        /// 3在顶点上
        /// 2在边上
        /// 1在内部
        /// 0在外面
        int Point_in_polygon(Point tep)
        {
            for(int i = 0 ; i < num ; i++){
                if( p[i] == tep ) return 3;
            }
            for(int i = 0 ; i < num ; i++){
                if( l[i].point_on_seg(tep) ) return 2;
            }
            int tecnt = 0;
            for(int i = 0 ; i < num ; i++)
            {
                int j = (i + 1) % num;
                int c = sgn( (tep - p[j]) ^ (p[i] - p[j]) );
                int u = sgn( p[i].y - tep.y );
                int v = sgn( p[j].y - tep.y );
                if( c > 0 && u < 0 && v >=0 ) tecnt ++;
                if( c < 0 && u >= 0 && v < 0 ) tecnt --;
            }
            return tecnt != 0;
        }
    
    }pol;
    
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
    
        int t,n;
        cin >> t;
    
        while(t--)
        {
            Point p1,p2,j1,j3;
            cin >> p1.x >> p1.y >> p2.x >> p2.y >> j1.x >> j1.y >> j3.x >> j3.y;
            if( j1.x > j3.x ) swap(j1,j3);
    
            Line lp(p1,p2);
            Point j2,j4;
            j2.x = j3.x,j2.y = j1.y,j4.x = j1.x ,j4.y = j3.y;
            polygon pol;
            pol.p[0] = j1;
            pol.p[1] = j2;
            pol.p[2] = j3;
            pol.p[3] = j4;
            pol.l[0].input(j1,j2);pol.l[1].input(j2,j3),pol.l[2].input(j3,j4),pol.l[3].input(j4,j1);
            pol.num = 4;
            bool flag = 0;
            for(int i = 0; i < 4 ; i++)
                if( lp.segcrossseg(pol.l[i]) > 0 ){
                    flag = 1;
                    break;
                }
    
    
            if( flag ) cout <<'T' <<endl;
            else{
                    //cout << pol.Point_in_polygon(p1) << ' ' <<  pol.Point_in_polygon(p2) << endl;
                if( pol.Point_in_polygon(p1) && pol.Point_in_polygon(p2)  ) cout << 'T' << endl;
                else cout << 'F' <<endl;
            }
    
    
        }
    
    
    
        return 0;
    }
    

    3.6____计算凸包,周长

    Surround the Trees

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    using namespace std;
    const double eps = 1e-8;
    const double pi = acos( -1.0);
    
    ///Compares a double to zero
    int sgn(double x)
    {
        if( fabs(x) < eps ) return 0;
        if( x < 0 ) return -1;
        else return 1;
    }
    ///square of a double
    inline double sqr(double x) { return x * x; }
    /////////////////////////////////////////////////
    struct Point
    {
        double x,y;
        Point(){}               ///no arguments constructor
        Point(double _x,double _y) {
            x = _x , y = _y;    ///arguments constructor
        }
        /*void input(){
            scanf("%lf%lf",&x,&y);
        }
        void output(){
            printf("%.2f %.2f
    ",x,y);
        }*/
        bool operator == (Point b) const{
            return sgn(x - b.x) == 0 && sgn(y - b.y) == 0;
        }
        bool operator < (Point b) const{
            return sgn(x - b.x) == 0? sgn(y - b.y) < 0 : x < b.x;
        }
        ///数量积
        Point operator - (const Point &b) const{
            return Point(x - b.x , y - b.y);
        }
        Point operator + (const Point &b) const{
            return Point(x + b.x , y + b.y);
        }
        Point operator * (const double &k) const{
            return Point(x * k , y * k );
        }
        Point operator / (const double &k) const{
            return Point(x / k , y / k);
        }
        ///叉积
        double operator ^ (const Point &b) const{
            return x * b.y - y * b.x;
        }
        ///点积
        double operator * (const Point &b) const{
            return x * b.x + y * b.y;
        }
        ///线段的长度
        double len(){
            return hypot(x,y);  ///<cmath>
        }
        ///长度的平方
        double len2(){
            return x * x + y * y;
        }
        ///返回两点的距离
        double distance(Point p){
            return hypot( x - p.x , y - p.y );
        }
        ///计算 pa 和 pb 的夹角
        double rad(Point a,Point b){
            Point p = *this;
            return fabs( atan2( fabs( (a-p)^(b-p) )  , (a-p)*(b-p) ) );
        }
        ///化为长度为r的向量
        Point trunc(double r){
            double l = len();
            if( !sgn(l) ) return *this;
        }
        ///逆时针旋转90度
        Point rotleft(){
            return Point(y,-x);
        }
        ///顺时针旋转90度
        Point rotright(){
            return Point(y,-x);
        }
        ///绕着p点逆时针
        Point rotata(Point p,double angle){
            Point v = (*this) - p;
            double c = cos(angle) , s = sin(angle);
            return Point(p.x + v.x * c - v.y * s , p.y + v.x *s + v.y * c);
        }
    };
    
    struct Line
    {
        Point s,e;
        Line(){}
        Line( Point _s, Point _e ){ s =_s ; e=_e; }
        ///由斜倾角angle与任意直线一点确定直线 y = kx + b;
        void input( Point _s, Point _e ){ s =_s ; e=_e; }
    
        Line(Point p,double angle){
            s = p;
            if( sgn(angle - pi/2) == 0 )    e = (s + Point(0,1));
            else e = (s + Point(1,tan(angle)));
        }
        ///ax + by + c = 0;
        Line(double a,double b,double c){
            if( sgn(a) == 0 )
            {
                s = Point(0,-c/b);
                e = Point(1,-c/b);
            }
            else if(sgn(b) == 0)
            {
                s = Point(-c/a,0);
                e = Point(-c/a,1);
            }
            else
            {
                s = Point(0,-c/b);
                e = Point(1,(-c-a)/b);
            }
        }
        ///直线与线段相交判断
        ///-*this line -v seg
        ///2规范相交,1非规范相交,0不相交
        bool linecrossseg(Line v){
            return sgn( (v.s - e) ^ (s - e) ) * sgn(( v.e-e ) ^ (s -e) ) <= 0;
        }
    		///点与直线关系
        ///1在左侧
        ///2在右侧
        ///3在直线
        int relation(Point p){
            int c = sgn( (p-s) ^ (e -s) );
            if(c < 0) return 1;
            else if(c > 0) return 2;
            else return 3;
        }
        ///点在线段上的判断
        bool point_on_seg(Point p){
            return sgn((p-s)^(e-s) ) == 0 && sgn( (p-s)*(p-e) ) <= 0 ;
        }
        ///两向量平行(对应直线平行或重合)
        bool parallel(Line v){
            return sgn( (e-s)^( v.e - v.s ) ) == 0;
        }
        ///两直线关系 0-平行,1-重合,2-相交
        int linecrossline(Line v){
            if( (*this).parallel(v) )
                return v.relation(s) == 3;
            return 2;
        }
        ///得到交点,需先判断直线是否相交
        Point crosspoint(Line v){
            double a1 = ( v.e - v.s ) ^ ( s - v.s );
            double a2 = ( v.e - v.s ) ^ ( e - v.s );
            return Point( (s.x * a2 - e.x * a1)/(a2 - a1) , (s.y *a2 - e.y *a1)/(a2 - a1));
        }
    
        ///两线段相交判断
        ///2 规范相交
        ///1 非规范相交
        ///0 不想交
        int segcrossseg(Line v) {
            int d1 = sgn((e - s) ^ (v.s - s));
            int d2 = sgn((e - s) ^ (v.e - s));
            int d3 = sgn((v.e - v.s) ^ (s - v.s));
            int d4 = sgn((v.e - v.s) ^ (e - v.s));
            if ((d1 ^ d2) == -2 && (d3 ^ d4) == -2)return 2;
            return (d1 == 0 && sgn((v.s - s) * (v.s - e)) <= 0) ||
                (d2 == 0 && sgn((v.e - s) * (v.e - e)) <= 0) ||
                (d3 == 0 && sgn((s - v.s) * (s - v.e)) <= 0) ||
                (d4 == 0 && sgn((e - v.s) * (e - v.e)) <= 0);
        }
    
    };
    
    struct triangle
    {
        Point A,B,C;
        Line a,b,c;
    
        triangle(){}
        triangle(Point _A,Point _B,Point _C){ A = _A ; B = _B ; C = _C;}
    
        ///求重心
        Point incenter(){
            return Point( ( A.x + B.x + C.x ) / 3, ( A.y + B.y + C.y ) / 3);
        }
    
    };
    
    const int maxp = 100;
    const int maxl = 200;
    
    struct polygon
    {
        int n;      ///点的数量
        Point p[maxp];
        Line l[maxl];
    
    
        struct cmp{
            Point p;
            cmp(const Point &p0){ p = p0;}
            bool operator()( const Point &aa ,const Point &bb){
                Point a = aa,b = bb;
                int d = sgn( (a-p)^(b-p) );
                if(d == 0)  return sgn( a.distance(p) - b.distance(p)) < 0;
                return d > 0;
            }
        };
        ///极角排序
        ///mi为最左下角的点
        void norm(){
            Point mi = p[0];
            for(int i = 1; i < n; i ++) mi = min(mi,p[i]);
            sort(p, p + n, cmp(mi) );
        }
        /// 判断任意点与多边形的关系
        /// 3在顶点上
        /// 2在边上
        /// 1在内部
        /// 0在外面
        int Point_in_polygon(Point tep)
        {
            for(int i = 0 ; i < n ; i++){
                if( p[i] == tep ) return 3;
            }
            for(int i = 0 ; i < n; i++){
                if( l[i].point_on_seg(tep) ) return 2;
            }
            int tecnt = 0;
            for(int i = 0 ; i < n ; i++)
            {
                int j = (i + 1) % n;
                int c = sgn( (tep - p[j]) ^ (p[i] - p[j]) );
                int u = sgn( p[i].y - tep.y );
                int v = sgn( p[j].y - tep.y );
                if( c > 0 && u < 0 && v >=0 ) tecnt ++;
                if( c < 0 && u >= 0 && v < 0 ) tecnt --;
            }
            return tecnt != 0;
        }
    
        /// 得到凸包
        /// 得到的凸包里的点编号是 0 ~ n-1 的
        void getconvex(polygon &convex)
        {
            sort(p , p + n);
            convex.n = n;
            for(int i = 0 ; i < min(n,2) ; i++){
                convex.p[i] = p[i];
            }
            ///特判
            if( convex.n == 2 && (convex.p[0] == convex.p[1]) ) convex.n--;
            if( n <= 2) return;
            int &top = convex.n;
            top = 1;
            for(int i = 2; i < n ; i++){
                while(top && sgn( (convex.p[top] - p[i]) ^ (convex.p[top-1] - p[i])) <= 0 ) top --;
                convex.p[++top] = p[i];
            }
            int temp = top;
            convex.p[++top] = p[n-2];
            for(int i = n - 3; i >=0 ; i--)
            {
                while( top!=temp && sgn( (convex.p[top] - p[i]) ^ (convex.p[top-1] - p[i]) ) <=0 ) top--;
                convex.p[++top] = p[i];
            }
            if( convex.n == 2&& ( convex.p[0] == convex.p[1]) ) convex.n --;    ///特判
            convex.norm();///得到的是顺时针的点,排序后逆时针
        }
    
        ///判断是不是凸多边形
        bool isconvex(){
            bool s[2];
            memset(s,false,sizeof(s));
            for(int i = 0 ; i < n ; i++){
                int j = (i + 1) % n;
                int k = (j + 1) % n;
                s[ sgn((p[j] - p[i]) ^ (p[k]-p[i]) ) + 1] =true;
            }
        }
    
        ///得到周长
        double getcircumference(){
            double sum = 0;
            for(int i = 0 ; i < n ; i++){
                sum += p[i].distance( p[(i + 1)%n] );
            }
            return sum;
        }
    
        ///得到面积
        double getarea()
        {
            double sum = 0;
            for(int i = 0;  i < n ; i++){
                sum += ( p[i]^p[ (i+1)%n ] );
            }
            return fabs(sum)/2;
        }
    };
    
    
    int main()
    {
    
        ios::sync_with_stdio(false);
        cin.tie(0);
    
        int t,n;
        while( true )
        {
            scanf("%d",&n);
            if( n== 0) break;
            polygon pol;
            pol.n = n;
            for(int i = 0; i < n ; i++) scanf("%lf %lf",&pol.p[i].x,&pol.p[i].y);
            for(int i = 0 ; i <n ; i++) pol.l[i].input( pol.p[i] , pol.p[ (i + 1)%n ] );
    
            polygon poly;
            pol.getconvex(poly);
    
            //printf("%d
    ",poly.n) ;
            //printf("%.2f
    ",pol.getcircumference());
            ///如果只有两个点要特判,看计算凸包的公式就明白了
            if( poly.n == 2 ) printf("%.2f
    ",poly.getcircumference()/2 );
            else printf("%.2f
    ",poly.getcircumference() );
        }
    
        return 0;
    }
    
    

    3.7____平面几何

    Keiichi Tsuchiya the Drift King

    2018焦作——ICPC

    #include <bits/stdc++.h>
    using namespace std;
    
    const double pi = acos(-1);
    const double eps = 1e-8;
    
    int sgn(double x)
    {
        if( fabs(x) < eps ) return 0;
        if( x < 0 ) return -1;
        else return 1;
    }
    
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
    
        int t;
        scanf("%d",&t);
        while(t--)
        {
            double a,b,d,r;
            scanf("%lf%lf%lf%lf",&a,&b,&r,&d);
            double delta = d * pi / 180.0;
    
            double stand = atan( b/ (a+r) );
            if( sgn( delta - stand ) >= 0 )
            {
                printf("%.12f
    ",sqrt( b*b + (a + r)*(a + r) ) - r);
            }
            else
            {
                double ans = sin(delta) * (b - (a+r)*tan(delta)) + (a+r)/cos(delta) - r;
                printf("%.12f
    ",ans);
            }
    
        }
    
        return 0;
    }
    
    

    3.8____最小圆覆盖

    Buried memory

    HDU_3007

    #include <bits/stdc++.h>
    using namespace std;
    
    const double pi = acos(-1);
    const double eps = 1e-8;
    
    inline int sgn(double x)
    {
        if( fabs(x) < eps ) return 0;
        if( x < 0 ) return -1;
        else return 1;
    }
    
        int n;
    
    struct Point{
        double x,y;
        Point(){}
        Point(double _x,double _y){ x = _x;y=_y; }
    }p[510];
    
    inline double dis(Point a,Point b )
    {
        return hypot( a.x - b.x,a.y - b.y );
    }
    
    
    ///求三角形外接圆圆心
    inline Point circle_certer(const Point a,const Point b,const Point c)
    {
        Point center;
        double a1 = b.x - a.x, b1 = b.y - a.y,c1 = (a1 * a1 + b1 * b1) / 2;
        double a2 = c.x - a.x, b2 = c.y - a.y,c2 = (a2 * a2 + b2 *b2) / 2;
        double d = a1 * b2 - a2 *b1;
        center.x = a.x + (c1 * b2 - c2 *b1) /d;
        center.y = a.y + (a1 * c2 - a2 *c1) /d;
        return center;
    }
    
    void min_cover_circle(Point &c,double &r)
    {
        random_shuffle(p,p+n);                          ///将点的排列顺序随机化,降低枚举的时间复杂度
        c = p[0],r = 0;                                 ///从第一个点开始,
        for(int i = 1; i < n ; i++ )
            if( sgn( dis(p[i],c) - r ) > 0 ){           ///新的点,在原来那个圆的外面
                c = p[i],r = 0;
                for(int j = 0; j < i ; j++){            ///从新检查前面的点是否都在圆内
                     if( sgn( dis(p[j],c) - r ) > 0 ){  ///如果之前的点在新园的外面,从新定圆
                        c.x = (p[i].x + p[j].x ) /2;
                        c.y = (p[i].y + p[j].y ) /2;
                        r = dis( p[j],c );
                        for(int k = 0 ;  k < j ; k ++){
                            if( sgn(dis(p[k],c) - r)  > 0){///如果两点定的点不能满足,则选择3个点来确定
                                c = circle_certer(p[i],p[j],p[k]);
                                r = dis(p[i],c);
                            }
                        }
                     }
                }
            }
    }
    
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
    
        while(~scanf("%d",&n) && n != 0)
        {
            Point ans;
            double ansr;
            for(int i =0 ; i < n ; i++)
            {
                scanf("%lf%lf",&p[i].x,&p[i].y);
            }
            min_cover_circle(ans,ansr);
            printf("%.2f %.2f %.2f
    ",ans.x,ans.y,ansr);
        }
    
    
    
    
        return 0;
    }
    
    

    3.9____空凸包(计算几何 + dp)

    [Empty Convex Polygons](Empty Convex Polygons - HDU 6219 - Virtual Judge (vjudge.net))

    ICPC_2017沈阳

    #include <iostream>
    #include <cmath>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    typedef double type_p;
    const double eps = 1e-6;
    const int maxn = 510;
    double dp[maxn][maxn];
    inline double eq(double x, double y) {
        return fabs(x-y)<eps;
    }
    inline int eq(int x, int y) {
        return x==y;
    }
    struct point {
        type_p x,y;
    };
    type_p xmult(point a, point b, point o)
    {
        return (a.x-o.x)*(o.y-b.y)-(a.y-o.y)*(o.x-b.x);//b at ao left if negative, at right if positive
    }
    type_p dist(point a, point b)
    {
        return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
    }
    point o;
    bool cmp_angle(point a,point b) {
        if(eq(xmult(a,b,o),0.0)){
            return dist(a,o)<dist(b,o);
        }
        return xmult(a,o,b)>0;
    }
    /*
     Input:  p:  Point set
     pn: size of the point set
    
     Output: the area of the largest empty convex
     */
    double empty_convex(point *p, int pn) {
        double ans=0;
        for(int i=0; i<pn; i++){
            for(int j=0; j<pn; j++){
                dp[i][j]=0;
            }
        }
        for(int i=0; i<pn; i++){
            int j = i-1;
            while(j>=0 && eq(xmult(p[i], p[j], o),0.0))j--;//coline
            bool flag= j==i-1;
            while(j>=0){
                int k = j-1;
                while(k >= 0 && xmult(p[i],p[k],p[j])>0)k--;
                double area = fabs(xmult(p[i],p[j],o))/2;
                if(k >= 0)area+=dp[j][k];
                if(flag) dp[i][j]=area;
                ans=max(ans,area);
                j=k;
            }
            if(flag){
                for(int j=1; j<i; j++) {
                    dp[i][j] = max(dp[i][j],dp[i][j-1]);
                }
            }
        }
        return ans;
    }
    double largest_empty_convex(point *p, int pn) {
        point data[maxn];
        double ans=0;
        for(int i=0; i<pn; i++) {
            o=p[i];
            int dn=0;
            for(int j=0; j<pn; j++)
            {
                if(p[j].y>o.y||(p[j].y==o.y&&p[j].x>=o.x))
                {
                    data[dn++]=p[j];
                }
            }
            sort(data, data+dn, cmp_angle);
            ans=max(ans, empty_convex(data, dn));
        }
        return ans;
    }
    int main() {
        point p[110];
        int t;
        scanf("%d",&t);
        while(t--) {
            int pn;
            scanf("%d",&pn);
            for(int i=0; i<pn; i++)
            {
                scanf("%lf%lf",&p[i].x,&p[i].y);
            }
            printf("%.1f
    ",largest_empty_convex(p,pn));
        }
        return 0;
    }
    
    
  • 相关阅读:
    JavaScript常用正則表達式
    详尽解析window.event对象
    DWR的类却无法在js里用
    javascript控制小数点精度
    49. Group Anagrams
    48. Rotate Image
    64. Minimum Path Sum
    63. Unique Paths II
    62. Unique Paths
    53. Maximum Subarray
  • 原文地址:https://www.cnblogs.com/hoppz/p/14691758.html
Copyright © 2020-2023  润新知