[计算几何]补题

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\n",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\n",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\n",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\n",poly.n) ;
        //printf("%.2f\n",pol.getcircumference());
        ///如果只有两个点要特判,看计算凸包的公式就明白了
        if( poly.n == 2 ) printf("%.2f\n",poly.getcircumference()/2 );
        else printf("%.2f\n",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\n",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\n",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\n",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\n",largest_empty_convex(p,pn));
    }
    return 0;
}

posted @ 2021-04-22 21:59  Hoppz  阅读(49)  评论(0编辑  收藏  举报