计算几何入门题#1(点,线基本关系,点积叉积的理解)

来源:互联网 发布:数据泄露是什么 编辑:程序博客网 时间:2024/06/01 08:51

POJ 2318(叉积判左右)

题意:

给一个有很多隔栏的箱子以及一些玩具的坐标,求箱子每个区域内玩具个数。

思路:

其实就是二分+叉积判断。
通过二分隔栏线段,得到一个玩具所在区域。
玩具(x,y)所在区域的判断方式是与左边隔栏叉积小于0,右边大于0.
第一次真正意义上做计算几何的题,对叉积理解还不够充分,连WA好多发,啊。。

代码:

/** @author FreeWifi_novicer* language : C++/C*/#include<cstdio>#include<iostream>#include<cstring>#include<cstdlib>#include<cmath>#include<algorithm>#include<string>#include<map>#include<set>#include<vector>#include<queue>using namespace std;#define clr( x , y ) memset(x,y,sizeof(x))#define cls( x ) memset(x,0,sizeof(x))#define mp make_pair#define pb push_backtypedef long long lint;typedef long long ll;typedef long long LL;const double eps(1e-6) ;const int maxn = 5050 ;struct Point{    int x , y ;    Point( int x = 0 , int y = 0 ) : x(x) , y(y){} ;} ;typedef Point Vector ;int det( Vector a , Vector b ){    return a.x * b.y - a.y * b.x ;}int u[maxn] , l[maxn] ;int cnt[maxn] ;int main(){  //freopen("input.txt","r",stdin);    int n , m ;    int x1 , y1 , x2 , y2 ;    while( cin >> n >> m >> x1 >> y1 >> x2 >> y2 && n ){        cls( cnt ) ; cls( u ) ; cls( l ) ;        for( int i = 0 ; i < n ; i++ ){            scanf( "%d%d" , u+i , l+i ) ;        }        u[n] = l[n] = x2 ;        for( int i = 0 ; i < m ; i++ ){            int X , Y ;            scanf( "%d%d" , &X , &Y ) ;            int pos ;            int L = 0 , R = n ;            while( L <= R ){                int M = ( L + R ) >> 1 ;                if( det( Vector( u[M] - X , y1 - Y ) , Vector( l[M] - X , y2 - Y ) ) < 0 ){                    pos = M ;                    R = M - 1 ;                }                else                    L = M + 1 ;            }            cnt[pos] ++ ;        }        for( int i = 0 ; i <= n ; i++ ){            printf( "%d: %d\n" , i , cnt[i] ) ;        }        puts("");    }    return 0;}

POJ 2398(叉积判左右)

题意:

给一个有很多隔栏的箱子以及一些玩具的坐标,求箱子区域内玩具个数为t(t>0)的区域数。

思路:

上一题改改代码顺手A了它。。

代码:

/** @author FreeWifi_novicer* language : C++/C*/#include<cstdio>#include<iostream>#include<cstring>#include<cstdlib>#include<cmath>#include<algorithm>#include<string>#include<map>#include<set>#include<vector>#include<queue>using namespace std;#define clr( x , y ) memset(x,y,sizeof(x))#define cls( x ) memset(x,0,sizeof(x))#define mp make_pair#define pb push_backtypedef long long lint;typedef long long ll;typedef long long LL;const double eps(1e-6) ;const int maxn = 5050 ;struct Point{    int x , y ;    Point( int x = 0 , int y = 0 ) : x(x) , y(y){} ;} ;typedef Point Vector ;int det( Vector a , Vector b ){    return a.x * b.y - a.y * b.x ;}int u[maxn] , l[maxn] ;int cnt[maxn] ;map<int,int>ms;int main(){  //freopen("input.txt","r",stdin);    int n , m ;    int x1 , y1 , x2 , y2 ;    while( cin >> n >> m >> x1 >> y1 >> x2 >> y2 && n ){        ms.clear() ;        cls( cnt ) ; cls( u ) ; cls( l ) ;        for( int i = 0 ; i < n ; i++ ){            scanf( "%d%d" , u+i , l+i ) ;        }        sort( u , u+n ) ;        sort( l , l+n ) ;        u[n] = l[n] = x2 ;        for( int i = 0 ; i < m ; i++ ){            int X , Y ;            scanf( "%d%d" , &X , &Y ) ;            int pos ;            int L = 0 , R = n ;            while( L <= R ){                int M = ( L + R ) >> 1 ;                if( det( Vector( u[M] - X , y1 - Y ) , Vector( l[M] - X , y2 - Y ) ) < 0 ){                    pos = M ;                    R = M - 1 ;                }                else                    L = M + 1 ;            }            cnt[pos] ++ ;        }        for( int i = 0 ; i <= n ; i++ ){            ms[cnt[i]] ++ ;        }        map<int,int>::iterator it = ms.begin() ;        puts("Box");        for( ; it != ms.end() ; it++ ){            if( it->first > 0 )                printf("%d: %d\n", it->first , it->second ) ;        }    }    return 0;}

POJ 3304 Segments (判断线段直线相交)

题意:

输入一些线段,问是否存在一条直线使所有线段在直线上的投影都有公共点。

思路:

若存在一条直线使所有线段在直线上的投影都有公共点,等价于存在一条直线与所有线段相交。

证明:
存在一条直线使所有线段在直线上的投影都有公共点,作这条直线的垂线,则垂线与所有线段相交。

枚举所有线段的两个端点连成直线,若这条直线经过所有线段,则存在一条直线与所有线段相交。

证明:若存在一条直线与所有线段相交,则可保持该直线与所有线段相交,将其平移至交于某一端点,再旋转该线段,使其交于第二个端点。

代码:

/* * @author FreeWifi_novicer * language : C++/C */#include<cstdio>#include<iostream>#include<cstring>#include<cstdlib>#include<cmath>#include<algorithm>#include<string>#include<map>#include<set>#include<vector>#include<queue>using namespace std;#define clr( x , y ) memset(x,y,sizeof(x))#define cls( x ) memset(x,0,sizeof(x))#define mp make_pair#define pb push_backtypedef long long lint;typedef long long ll;typedef long long LL;const double eps(1e-10) ;const int maxn = 100 + 5 ;struct Point{    double x , y ;    Point( double x = 0 , double y = 0 ) : x(x) , y(y) {}};typedef Point Vector ; Vector operator - ( Point a , Point b ){    return Vector( a.x - b.x , a.y - b.y ) ;}double det( Vector a , Vector b ){    return a.x * b.y - a.y * b.x ;}int dcmp( double x ){    if( fabs(x) < eps ) return 0 ;    return ( x < 0 )? -1 : 1 ;}int segLineCross( Point a1 , Point a2 , Point b1 , Point b2 ){      int d1 = dcmp( det( a2 - a1 , b1 - a1 ) );    int d2 = dcmp( det( a2 - a1 , b2 - a1 ) );    //cout << d1 << ' ' << d2 << endl ;    if( (d1^d2) == -2 )         return 0 ;      if( d1 == 0 || d2 == 0 )          return 1 ;      return -1 ;  }Point p[maxn << 2] ;bool check( Point a , Point b , int n ){    if( dcmp( a.x - b.x ) == 0 && dcmp( a.y - b.y ) == 0 )        return false ;    for( int i = 1 ; i < 2 * n ; i += 2 ){        if( segLineCross( a , b , p[i] , p[i+1] ) == -1 )            return false ;    }    return true ;}bool work( int n ){    for( int i = 1 ; i < 2 * n ; i++ ){        for( int j = i + 1 ; j <= 2 * n ; j++ ){            if( check( p[i] , p[j] , n ) )                return true ;        }    }    return false ;}int main(){      //freopen("input.txt","r",stdin);    int t ; cin >> t ;    while( t-- ){        int n ; cin >> n ;        for( int i = 1 ; i <= 2 * n ; i++ ){            cin >> p[i].x >> p[i].y ;        }        if( work( n ) )            puts( "Yes!" ) ;        else            puts( "No!" ) ;    }    return 0;}

POJ 1029 Intersecting Lines(直线相交)

题意:

判断两条直线相交还是平行,重合?

思路:

裸题,上模板A过去。

代码:

/** @author FreeWifi_novicer* language : C++/C*/#include<cstdio>#include<iostream>#include<cstring>#include<cstdlib>#include<cmath>#include<algorithm>#include<string>#include<map>#include<set>#include<vector>#include<queue>using namespace std;#define clr( x , y ) memset(x,y,sizeof(x))#define cls( x ) memset(x,0,sizeof(x))#define mp make_pair#define pb push_backtypedef long long lint;typedef long long ll;typedef long long LL;const double pi = acos( -1.0 ) ;const double eps = 1e-8 ;inline double sqr( double x ) { return x * x ; } inline int cmp( double x ){    if( fabs(x) < eps ) return 0 ;    if( x > 0 ) return 1 ;    return -1 ;}struct Point{    double x , y ;    Point(){} ;    Point( double a , double b ):x(a) , y(b){}    void input(){        scanf( "%lf%lf" , &x , &y ) ;    }    double norm(){        return sqrt( sqr( x ) + sqr( y ) ) ;    }    friend Point operator + ( const Point &a , const Point &b ) { return Point( a.x + b.x , a.y + b.y ) ; }    friend Point operator - ( const Point &a , const Point &b ) { return Point( a.x - b.x , a.y - b.y ) ; }    friend Point operator * ( const Point &a , const double &b ) { return Point( a.x * b , a.y * b ) ; }    friend Point operator * ( const double &a , const Point &b ) { return Point( b.x * a , b.y * a ) ; }    friend Point operator / ( const Point &a , const double &b ) { return Point( a.x / b , a.y / b ) ; }    friend bool operator == ( const Point &a , const Point &b ) { return cmp( a.x - b.x ) == 0 && cmp( a.y - b.y ) == 0 ; }};typedef Point Vector ;double dot( const Point &a , const Point &b ){ return a.x * b.x + a.y * b.y ; }double det( const Point &a , const Point &b ){ return a.x * b.y - a.y * b.x ; }double dist( const Point &a , const Point &b ){ return ( a - b ).norm() ; }struct Line{    Point a , b ;    Line(){}    Line( Point x , Point y ): a(x) , b(y){}};bool parallel( Line a , Line b ){    return !cmp( det( a.a - a.b , b.a - b.b ) ) ;}bool line_make_point( Line a , Line b , Point &res ){    if( parallel( a , b ) ) return false ;    double s1 = det( a.a - b.a , b.b - b.a ) ;    double s2 = det( a.b - b.a , b.b - b.a ) ;    res = ( s1 * a.b - s2 * a.a ) / ( s1 - s2 ) ;    return true ;}double dis_to_line( Point P , Point A , Point B ){    Vector v1 = B - A , v2 = P - A ;    return fabs( det( v1 , v2 ) ) / v1.norm() ;}int main(){  //freopen("input.txt","r",stdin);    int n ; cin >> n ;    puts("INTERSECTING LINES OUTPUT") ;    while( n-- ){        Point a1 , b1 , a2 , b2 ;        a1.input() ;        b1.input() ;        a2.input() ;        b2.input() ;        Line l1( a1 , b1 ) , l2( a2 , b2 ) ;        Point res ;        if( parallel( l1 , l2 ) && !cmp(dis_to_line( l1.a , l2.a , l2.b )) )            puts( "LINE" ) ;        else if( parallel( l1 , l2 ) && cmp(dis_to_line( l1.a , l2.a , l2.b )) )            puts( "NONE" ) ;        else if( line_make_point( l1 , l2 , res ) ){            printf( "POINT %.2f %.2f\n" , res.x , res.y ) ;        }    }    puts( "END OF OUTPUT" ) ;    return 0;}

POJ 1556 The Doors(线段相交判定 + 最短路)

题意:

坐标系中有一个10*10的正方形房间,房间中有n面沿y轴方向的墙,每面墙上有两扇门,
求从房间最左边的(0,5)处到达房间最右边的(10,5)处的最短距离

思路:

可以算出,总共有4 * n+2个端点,其中包括入口与出口,以及3 * n条障碍线段,那么我们求出来所有点之间的距离,建立邻接矩阵,跑一遍flyod,dijkstra或者spfa都行,总之求出入口到出口的最短路即可。
至于建图方法,判断两个端点所成线段是否与任一障碍线段交,若相交那么距离无穷大,否则计算两点距离。

代码:

代码4500B,其中4000B是模板

/** @author FreeWifi_novicer* language : C++/C*/#include<cstdio>#include<iostream>#include<cstring>#include<cstdlib>#include<cmath>#include<algorithm>#include<string>#include<map>#include<set>#include<vector>#include<queue>using namespace std;#define clr( x , y ) memset(x,y,sizeof(x))#define cls( x ) memset(x,0,sizeof(x))#define mp make_pair#define pb push_backtypedef long long lint;typedef long long ll;typedef long long LL;const double inf = 10000000 ;const double pi = acos( -1.0 ) ;const double eps = 1e-8 ;inline double sqr( double x ) { return x * x ; } inline int cmp( double x ){    if( fabs(x) < eps ) return 0 ;    if( x > 0 ) return 1 ;    return -1 ;}struct Point{    double x , y ;    Point(){} ;    Point( double a , double b ):x(a) , y(b){}    void input(){        scanf( "%lf%lf" , &x , &y ) ;    }    double norm(){        return sqrt( sqr( x ) + sqr( y ) ) ;    }    friend Point operator + ( const Point &a , const Point &b ) { return Point( a.x + b.x , a.y + b.y ) ; }    friend Point operator - ( const Point &a , const Point &b ) { return Point( a.x - b.x , a.y - b.y ) ; }    friend Point operator * ( const Point &a , const double &b ) { return Point( a.x * b , a.y * b ) ; }    friend Point operator * ( const double &a , const Point &b ) { return Point( b.x * a , b.y * a ) ; }    friend Point operator / ( const Point &a , const double &b ) { return Point( a.x / b , a.y / b ) ; }    friend bool operator == ( const Point &a , const Point &b ) { return cmp( a.x - b.x ) == 0 && cmp( a.y - b.y ) == 0 ; }};typedef Point Vector ;double dot( const Point &a , const Point &b ){ return a.x * b.x + a.y * b.y ; }double det( const Point &a , const Point &b ){ return a.x * b.y - a.y * b.x ; }double dist( const Point &a , const Point &b ){ return ( a - b ).norm() ; }struct Line{    Point a , b ;    Line(){}    Line( Point x , Point y ): a(x) , b(y){}};bool segment_inter( Point a1 , Point a2 , Point b1 , Point b2 ){    double c1 = det( a2 - a1 , b1 - a1 ) , c2 = det( a2 - a1 , b2 - a1 ) ,            c3 = det( b2 - b1 , a1 - b1 ) , c4 = det( b2 - b1 , a2 - b1 ) ;    bool tmp = ( ( cmp( c1 ) * cmp( c2 ) < 0 ) && ( cmp( c3 ) * cmp( c4 ) < 0 ) );    return tmp ;}const int maxn = 205 ;vector<Point> pt;vector<Line> L;bool v[maxn] ;double G[maxn][maxn] ;double dis[maxn] ;void build( int n ){    for( int i = 0 ; i < 4 * n + 2 ; i++ ){        for( int j = 0 ; j < 4 * n + 2 ; j++ ){            bool ok = true ;            for( int k = 0 ; k < 3 * n ; k++ ){                if( segment_inter( pt[i] , pt[j] , L[k].a , L[k].b ) ){                    ok = false ;                    break ;                }            }            if( ok )                G[i+1][j+1] = dist( pt[i] , pt[j] ) ;            else                G[i+1][j+1] = (double)inf ;        }    }}double dijkstra( int n ){    for( int i = 1 ; i <= n ; i++ ) dis[i] = G[1][i] ;    dis[1] = 0 ;    cls( v ) ;    for( int i = 1 ; i <= n ; i++ ){        int mark = 1 ;        double mindis = (double)inf ;        for( int j = 1 ; j <= n ; j++ ){            if( !v[j] && dis[j] < mindis ){                mindis = dis[j] ;                mark = j ;            }        }        v[mark] = 1 ;        for( int j = 1 ; j <= n ; j++ )            if( !v[j] && G[mark][j] < inf )                dis[j] = min( dis[j] , dis[mark] + G[mark][j] ) ;    }    return dis[n] ;}int main(){  //freopen("input.txt","r",stdin);    int n ;    while( cin >> n && n > -1 ){        pt.clear() ;        L.clear() ;        Point p( 0.0 , 5.0 ) ;        pt.pb(p) ;        for( int i = 1 ; i <= n ; i++ ){            double x , y1 , y2 , y3 , y4 ;            scanf( "%lf%lf%lf%lf%lf" , &x , &y1 , &y2 , &y3 , &y4 ) ;            Point p1( x , y1 ) , p2( x , y2 ) , p3( x , y3 ) , p4( x , y4 ) ;            pt.pb( p1 ) ;             pt.pb( p2 ) ;             pt.pb( p3 ) ;             pt.pb( p4 ) ;             L.pb( Line( Point( x , 0.0 ) , p1 ) ) ;            L.pb( Line( p2 , p3 ) ) ;            L.pb( Line( p4 , Point( x , 10.0 ) ) ) ;        }        pt.pb( Point( 10.0 , 5.0 ) ) ;        build(n) ;        double ans = dijkstra( 4*n + 2 ) ;        printf( "%.2f\n" , ans ) ;    }    return 0;}

POJ 1696 Space Ant(极角排序)

题意:

一只仅能左拐的蚂蚁,有n个点要去,要求设计爬行方案,使能去尽可能多的点,且保证爬行轨迹无交叉。

思路:

初见惊为神题,百思不得其解,后来知道了极角排序,发现实在是水题啊。。
先看样例1的图:
Alt text
因为只能左拐,所以起点应尽可能在所有点的最下方,且最左边;

然后对于每一个点,下一个要去的点,要尽可能在以自己为原点,极角较小的方向上,即自己的“右边”,如果极角相同则选择较小距离的点。

然后照着模拟下去就行了,因为没有重点,所以一定可以走完所有点,方案其实就是画一个逆时针螺旋线遍历所有点。

代码:

/** @author FreeWifi_novicer* language : C++/C*/#include<cstdio>#include<iostream>#include<cstring>#include<cstdlib>#include<cmath>#include<algorithm>#include<string>#include<map>#include<set>#include<vector>#include<queue>using namespace std;#define clr( x , y ) memset(x,y,sizeof(x))#define cls( x ) memset(x,0,sizeof(x))#define mp make_pair#define pb push_backtypedef long long lint;typedef long long ll;typedef long long LL;const double pi = acos( -1.0 ) ;const double eps = 1e-8 ;inline double sqr( double x ) { return x * x ; } inline int cmp( double x ){    if( fabs(x) < eps ) return 0 ;    if( x > 0 ) return 1 ;    return -1 ;}struct Point{    double x , y ;    Point(){} ;    Point( double a , double b ):x(a) , y(b){}    void input(){        scanf( "%lf%lf" , &x , &y ) ;    }    double norm(){        return sqrt( sqr( x ) + sqr( y ) ) ;    }    friend Point operator + ( const Point &a , const Point &b ) { return Point( a.x + b.x , a.y + b.y ) ; }    friend Point operator - ( const Point &a , const Point &b ) { return Point( a.x - b.x , a.y - b.y ) ; }    friend Point operator * ( const Point &a , const double &b ) { return Point( a.x * b , a.y * b ) ; }    friend Point operator * ( const double &a , const Point &b ) { return Point( b.x * a , b.y * a ) ; }    friend Point operator / ( const Point &a , const double &b ) { return Point( a.x / b , a.y / b ) ; }    friend bool operator == ( const Point &a , const Point &b ) { return cmp( a.x - b.x ) == 0 && cmp( a.y - b.y ) == 0 ; }};typedef Point Vector ;double dot( const Point &a , const Point &b ){ return a.x * b.x + a.y * b.y ; }double det( const Point &a , const Point &b ){ return a.x * b.y - a.y * b.x ; }double dist( const Point &a , const Point &b ){ return ( a - b ).norm() ; }const int maxn = 55 ;int pos ;struct Poi{    Point p ;    int no ;}last ;vector<Poi> p ;int res[maxn] ;bool acmp( const Poi &a , const Poi &b ){    int tmp = cmp( det( a.p - last.p , b.p - last.p ) ) ;    if( tmp != 0 ) return tmp > 0 ;    return dist( a.p , last.p ) < dist( b.p ,last.p ) ;}bool lowcmp( const Poi &a , const Poi &b ){    if( a.p.y != b.p.y ) return a.p.y < b.p.y ;    return a.p.x < b.p.x ;}int main(){    //freopen("input.txt","r",stdin);    int t ; cin >> t ;    while( t -- ){        int n ; cin >> n ;        for( int i = 1 ; i <= n ; i++ ){            Poi t ;            cin >> t.no >> t.p.x >> t.p.y ;            p.pb( t ) ;        }        sort( p.begin() , p.end() , lowcmp ) ;        vector<Poi>::iterator it = p.begin() ;        last = *it ;        p.erase( p.begin() ) ;        printf( "%d %d" , n , last.no ) ;        for( int i = 1 ; i < n ; i++ ){            sort( p.begin() , p.end() , acmp ) ;            it = p.begin() ;            last = *it ;            p.erase( p.begin() ) ;            printf( " %d" , last.no ) ;        }        puts("") ;    }    return 0;}

POJ1066 Treasure Hunt(线段相交)

题意:

一个房间被n面墙分成多个密室,告知宝藏坐标,求最少要炸几面墙才能取到宝藏。

思路:

其实也算一个大水题,枚举每一面墙的端点与宝藏点所成线段,与所有墙判断是否相交,相交+1,维护最小值,输出的时候+1即可。
ps.注意n = 0 .

代码:

/* * @author FreeWifi_novicer * language : C++/C */#include<cstdio>#include<iostream>#include<cstring>#include<cstdlib>#include<cmath>#include<algorithm>#include<string>#include<map>#include<set>#include<vector>#include<queue>using namespace std;#define clr( x , y ) memset(x,y,sizeof(x))#define cls( x ) memset(x,0,sizeof(x))#define mp make_pair#define pb push_backtypedef long long lint;typedef long long ll;typedef long long LL;const double pi = acos( -1.0 ) ;const double eps = 1e-8 ;inline double sqr( double x ) { return x * x ; } inline int cmp( double x ){    if( fabs(x) < eps ) return 0 ;    if( x > 0 ) return 1 ;    return -1 ;}struct Point{    double x , y ;    Point(){} ;    Point( double a , double b ):x(a) , y(b){}    void input(){        scanf( "%lf%lf" , &x , &y ) ;    }    double norm(){        return sqrt( sqr( x ) + sqr( y ) ) ;    }    friend Point operator + ( const Point &a , const Point &b ) { return Point( a.x + b.x , a.y + b.y ) ; }    friend Point operator - ( const Point &a , const Point &b ) { return Point( a.x - b.x , a.y - b.y ) ; }    friend Point operator * ( const Point &a , const double &b ) { return Point( a.x * b , a.y * b ) ; }    friend Point operator * ( const double &a , const Point &b ) { return Point( b.x * a , b.y * a ) ; }    friend Point operator / ( const Point &a , const double &b ) { return Point( a.x / b , a.y / b ) ; }    friend bool operator == ( const Point &a , const Point &b ) { return cmp( a.x - b.x ) == 0 && cmp( a.y - b.y ) == 0 ; }};typedef Point Vector ;double dot( const Point &a , const Point &b ){ return a.x * b.x + a.y * b.y ; }double det( const Point &a , const Point &b ){ return a.x * b.y - a.y * b.x ; }double dist( const Point &a , const Point &b ){ return ( a - b ).norm() ; }struct Line{    Point a , b ;    Line(){}    Line( Point x , Point y ): a(x) , b(y){}};bool segment_inter( Point a1 , Point a2 , Point b1 , Point b2 ){    double c1 = det( a2 - a1 , b1 - a1 ) , c2 = det( a2 - a1 , b2 - a1 ) ,            c3 = det( b2 - b1 , a1 - b1 ) , c4 = det( b2 - b1 , a2 - b1 ) ;    return cmp( c1 ) * cmp( c2 ) < 0 && cmp( c3 ) * cmp( c4 ) < 0 ;}const int maxn = 35 ;Line L[maxn] ;int main(){    //freopen("input.txt","r",stdin);    int n ;     while( cin >> n ){        for( int i = 1 ; i <= n ; i++ ){            L[i].a.input() ;            L[i].b.input() ;        }        Point p ;        p.input() ;        if( !n ){            printf( "Number of doors = 1\n" ) ;            continue ;        }        int cnt = 0 ;        int ans = 1000000 ;        for( int i = 1 ; i <= n ; i++ ){            cnt = 0 ;            for( int j = 1 ; j <= n ; j++ ){                if( segment_inter( L[i].a , p , L[j].a , L[j].b ) ) cnt++ ;            }            ans = min( ans , cnt ) ;            cnt = 0 ;            for( int j = 1 ; j <= n ; j++ ){                if( segment_inter( L[i].b , p , L[j].a , L[j].b ) ) cnt++ ;            }            ans = min( ans , cnt ) ;        }        ans ++ ;        cout << "Number of doors = " << ans << endl ;    }    return 0;}

POJ 2826 An Easy Problem?!(分类讨论,灵活运用叉积)

题意:

输入两块木板的截面坐标,求能收集多少雨水。

思路:

比较恶心的分类讨论。
主要的坑就是:
共线判断,
输出要加eps(可能输出-0.00。
多想想,想清楚。
附赠数据一组:
1
68.22 191.66 257.23 104.97
140.25 33.53 56.71 302.58
正确输出是0.00

代码:

/* * @author FreeWifi_novicer * language : C++/C */#include<cstdio>#include<iostream>#include<cstring>#include<cstdlib>#include<cmath>#include<algorithm>#include<string>#include<map>#include<set>#include<vector>#include<queue>using namespace std;#define clr( x , y ) memset(x,y,sizeof(x))#define cls( x ) memset(x,0,sizeof(x))#define mp make_pair#define pb push_backtypedef long long lint;typedef long long ll;typedef long long LL;const double pi = acos( -1.0 ) ;const double eps = 1e-8 ;inline double sqr( double x ) { return x * x ; } inline int cmp( double x ){    if( fabs(x) < eps ) return 0 ;    if( x > 0 ) return 1 ;    return -1 ;}struct Point{    double x , y ;    Point(){} ;    Point( double a , double b ):x(a) , y(b){}    void input(){        scanf( "%lf%lf" , &x , &y ) ;    }    double norm(){        return sqrt( sqr( x ) + sqr( y ) ) ;    }    friend Point operator + ( const Point &a , const Point &b ) { return Point( a.x + b.x , a.y + b.y ) ; }    friend Point operator - ( const Point &a , const Point &b ) { return Point( a.x - b.x , a.y - b.y ) ; }    friend Point operator * ( const Point &a , const double &b ) { return Point( a.x * b , a.y * b ) ; }    friend Point operator * ( const double &a , const Point &b ) { return Point( b.x * a , b.y * a ) ; }    friend Point operator / ( const Point &a , const double &b ) { return Point( a.x / b , a.y / b ) ; }    friend bool operator == ( const Point &a , const Point &b ) { return cmp( a.x - b.x ) == 0 && cmp( a.y - b.y ) == 0 ; }};typedef Point Vector ;double dot( const Point &a , const Point &b ){ return a.x * b.x + a.y * b.y ; }double det( const Point &a , const Point &b ){ return a.x * b.y - a.y * b.x ; }double dist( const Point &a , const Point &b ){ return ( a - b ).norm() ; }struct Line{    Point a , b ;    Line(){}    Line( Point x , Point y ): a(x) , b(y){}};Point line_make_point( Line a , Line b ){    double s1 = det( a.a - b.a , b.b - b.a ) ;    double s2 = det( a.b - b.a , b.b - b.a ) ;    Point res = ( s1 * a.b - s2 * a.a ) / ( s1 - s2 ) ;    return res ;}bool segment_inter( Point a1 , Point a2 , Point b1 , Point b2 ){    double c1 = det( a2 - a1 , b1 - a1 ) , c2 = det( a2 - a1 , b2 - a1 ) ,            c3 = det( b2 - b1 , a1 - b1 ) , c4 = det( b2 - b1 , a2 - b1 ) ;    return cmp( c1 ) * cmp( c2 ) <= 0 && cmp( c3 ) * cmp( c4 ) <= 0 ;}int main(){    //freopen("my.in","r",stdin);    //freopen("my.out","w+",stdout);    //freopen("input.txt","r",stdin);    int t ; cin >> t ;    while( t-- ){        Line b1 , b2 ;        b1.a.input() ; b1.b.input() ;        if( b1.b.y < b1.a.y ) swap( b1.a , b1.b ) ;        b2.a.input() ; b2.b.input() ;        if( b2.b.y < b2.a.y ) swap( b2.a , b2.b ) ;        if( b1.b.x > b2.b.x ) swap( b1 , b2 ) ;        if( !segment_inter( b1.a , b1.b , b2.a , b2.b ) ){            printf( "0.00\n" ) ;            continue ;        }        double ans ;        Point p = line_make_point( b1 , b2 ) ;        if( b1.b.y < b2.b.y ){            Line h1( b1.b , Point( b1.b.x , b1.b.y + 1000000 ) ) ;            if( segment_inter( h1.a , h1.b , p , b2.b ) ){                printf( "0.00\n" ) ;                continue ;            }            else{                if( cmp( det( b1.b - p , b2.b - p ) ) > 0 ){                    Line h2( b2.b , Point( b2.b.x , b2.b.y - 1000000 ) ) ;                    Point pp = line_make_point( h2 , b1 ) ;                    ans = fabs( det( b2.b - p , pp - p ) / 2.0 ) ;                }                else if( cmp( det( b1.b - p , b2.b - p ) ) < 0 ){                    Line h3( b1.b , Point( b1.b.x + 1000000 , b1.b.y ) ) ;                    Point pp = line_make_point( h3 , b2 ) ;                    ans = fabs( det( b1.b - p , pp - p ) / 2.0 ) ;                }                else{                    printf( "0.00\n" ) ;                    continue ;                }            }        }        else if( b1.b.y > b2.b.y ){            Line h1( b2.b , Point( b2.b.x , b2.b.y + 1000000 ) ) ;            if( segment_inter( h1.a , h1.b , p , b1.b ) ){                printf( "0.00\n" ) ;                continue ;            }            else{            if( cmp( det( b1.b - p , b2.b - p ) ) > 0 ){                Line h2( b2.b , Point( b2.b.x , b2.b.y - 1000000 ) ) ;                Point pp = line_make_point( h2 , b1 ) ;                ans = fabs( det( b2.b - p , pp - p ) / 2.0 ) ;            }            else if( cmp( det( b1.b - p , b2.b - p ) ) < 0 ){                Line h3( b2.b , Point( b2.b.x - 1000000 , b2.b.y ) ) ;                Point pp = line_make_point( h3 , b1 ) ;                ans = fabs( det( b2.b - p , pp - p ) / 2.0 ) ;            }            else{                printf( "0.00\n" ) ;                continue ;            }        }        }        else if( cmp( b1.b.y - b2.b.y ) == 0 ){            ans = fabs( det( b2.b - p , b1.b - p ) / 2.0 ) ;        }        if( ans > 0 - eps )            printf( "%.2f\n" , ans + eps ) ;        else{            printf( "%.2f\n" , 0.00 + eps ) ;        }    }    return 0;}

POJ 1410 Intersection(线段相交的种种情况)

题意:

输入一条线段的两个端点,一个矩形的两个顶点,判断线段与矩形是否相交(矩形包括4条边与边内区域)

思路:

从题目本身来说是个大水题。。但很考验模板的准确性。
判断为true有这么几种:

  1. 线段与四条边相交,包括端点相交
  2. 线段在矩形内
  3. 线段与四条边重叠共线或首尾相接

其实这题考虑不相交的情况可以简洁许多,至少从代码量上来说是这样的

强烈推荐试试这两组样例
0 18 8 12 1 1 11 11 -> F
9 7 9 2 4 3 9 6 -> T

代码:

/** @author FreeWifi_novicer* language : C++/C*/#include<cstdio>#include<iostream>#include<cstring>#include<cstdlib>#include<cmath>#include<algorithm>#include<string>#include<map>#include<set>#include<vector>#include<queue>using namespace std;#define clr( x , y ) memset(x,y,sizeof(x))#define cls( x ) memset(x,0,sizeof(x))#define mp make_pair#define pb push_backtypedef long long lint;typedef long long ll;typedef long long LL;const double pi = acos( -1.0 ) ;const double eps = 1e-8 ;inline double sqr( double x ) { return x * x ; } inline int cmp( double x ){    if( fabs(x) < eps ) return 0 ;    if( x > 0 ) return 1 ;    return -1 ;}struct Point{    double x , y ;    Point(){} ;    Point( double a , double b ):x(a) , y(b){}    void input(){        scanf( "%lf%lf" , &x , &y ) ;    }    double norm(){        return sqrt( sqr( x ) + sqr( y ) ) ;    }    friend Point operator + ( const Point &a , const Point &b ) { return Point( a.x + b.x , a.y + b.y ) ; }    friend Point operator - ( const Point &a , const Point &b ) { return Point( a.x - b.x , a.y - b.y ) ; }    friend Point operator * ( const Point &a , const double &b ) { return Point( a.x * b , a.y * b ) ; }    friend Point operator * ( const double &a , const Point &b ) { return Point( b.x * a , b.y * a ) ; }    friend Point operator / ( const Point &a , const double &b ) { return Point( a.x / b , a.y / b ) ; }    friend bool operator == ( const Point &a , const Point &b ) { return cmp( a.x - b.x ) == 0 && cmp( a.y - b.y ) == 0 ; }};typedef Point Vector ;double dot( const Point &a , const Point &b ){ return a.x * b.x + a.y * b.y ; }double det( const Point &a , const Point &b ){ return a.x * b.y - a.y * b.x ; }double dist( const Point &a , const Point &b ){ return ( a - b ).norm() ; }struct Line{    Point a , b ;    Line(){}    Line( Point x , Point y ): a(x) , b(y){}};bool Onsegment( Point p , Point s , Point t ){    return cmp( det( p - s , t - s ) ) == 0 && cmp( dot( p - s , p - t ) ) <= 0 ;}bool parallel( Line a , Line b ){    return !cmp( det( a.a - a.b , b.a - b.b ) ) ;}bool segment_inter( Point a1 , Point a2 , Point b1 , Point b2 ){    double c1 = det( a2 - a1 , b1 - a1 ) , c2 = det( a2 - a1 , b2 - a1 ) ,            c3 = det( b2 - b1 , a1 - b1 ) , c4 = det( b2 - b1 , a2 - b1 ) ;    return cmp( c1 ) * cmp( c2 ) < 0 && cmp( c3 ) * cmp( c4 ) < 0 ;}int main(){  //freopen("input.txt","r",stdin);    int t ; cin >> t ;    while( t-- ){        Line s ;        s.a.input() ; s.b.input() ;        Point top , bot ;        top.input() ; bot.input() ;        if( bot.x < top.x ){            swap( bot.x , top.x ) ;        }        if( bot.y > top.y ){            swap( bot.y , top.y ) ;        }        Line r1( top , Point( top.x , bot.y ) ) , r2( Point( bot.x , top.y ) , bot ) ;        Line r3( top , Point( bot.x , top.y ) ) , r4( Point( top.x , bot.y ) , bot ) ;        bool ok = false ;        if( segment_inter( r1.a , r1.b , s.a , s.b ) )            ok = true ;        if( segment_inter( r2.a , r2.b , s.a , s.b ) )            ok = true ;        if( segment_inter( r3.a , r3.b , s.a , s.b ) )            ok = true ;        if( segment_inter( r4.a , r4.b , s.a , s.b ) )            ok = true ;        if( Onsegment( s.a , r1.a , r1.b ) || Onsegment( s.b , r1.a , r1.b ) )            ok = true ;        if( Onsegment( s.a , r2.a , r2.b ) || Onsegment( s.b , r2.a , r2.b ) )            ok = true ;        if( Onsegment( s.a , r3.a , r3.b ) || Onsegment( s.b , r3.a , r3.b ) )            ok = true ;        if( Onsegment( s.a , r4.a , r4.b ) || Onsegment( s.b , r4.a , r4.b ) )            ok = true ;        if( parallel( s , r1 ) && s.a.x == r1.a.x ){            if( s.a.y >= min( r1.a.y , r1.b.y ) &&  s.a.y <= max( r1.a.y , r1.b.y ) )                ok = true ;            if( s.b.y >= min( r1.a.y , r1.b.y ) &&  s.b.y <= max( r1.a.y , r1.b.y ) )                ok = true ;            if( s.a.y <= min( r1.a.y , r1.b.y ) &&  s.b.y >= max( r1.a.y , r1.b.y ) )                ok = true ;            if( s.b.y <= min( r1.a.y , r1.b.y ) &&  s.a.y >= max( r1.a.y , r1.b.y ) )                ok = true ;        }        if( parallel( s , r2 ) && s.a.x == r2.a.x ){            if( s.a.y >= min( r2.a.y , r2.b.y ) &&  s.a.y <= max( r2.a.y , r2.b.y ) )                ok = true ;            if( s.b.y >= min( r2.a.y , r2.b.y ) &&  s.b.y <= max( r2.a.y , r2.b.y ) )                ok = true ;            if( s.a.y <= min( r2.a.y , r2.b.y ) &&  s.b.y >= max( r2.a.y , r2.b.y ) )                ok = true ;            if( s.b.y <= min( r2.a.y , r2.b.y ) &&  s.a.y >= max( r2.a.y , r2.b.y ) )                ok = true ;        }        if( parallel( s , r3 ) && s.a.y == r3.a.y ){            if( s.a.x >= min( r3.a.x , r3.b.x ) &&  s.a.x <= max( r3.a.x , r3.b.x ) )                ok = true ;            if( s.b.x >= min( r3.a.x , r3.b.x ) &&  s.b.x <= max( r3.a.x , r3.b.x ) )                ok = true ;            if( s.a.x <= min( r3.a.x , r3.b.x ) &&  s.b.x >= max( r3.a.x , r3.b.x ) )                ok = true ;            if( s.b.x <= min( r3.a.x , r3.b.x ) &&  s.a.x >= max( r3.a.x , r3.b.x ) )                ok = true ;        }        if( parallel( s , r4 ) && s.a.y == r4.a.y ){            if( s.a.x >= min( r4.a.x , r4.b.x ) &&  s.a.x <= max( r4.a.x , r4.b.x ) )                ok = true ;            if( s.b.x >= min( r4.a.x , r4.b.x ) &&  s.b.x <= max( r4.a.x , r4.b.x ) )                ok = true ;            if( s.a.x <= min( r4.a.x , r4.b.x ) &&  s.b.x >= max( r4.a.x , r4.b.x ) )                ok = true ;            if( s.b.x <= min( r4.a.x , r4.b.x ) &&  s.a.x >= max( r4.a.x , r4.b.x ) )                ok = true ;        }        if( top.x <= min( s.a.x , s.b.x )                 && top.y >= max( s.a.y , s.b.y )                 && bot.y <= min( s.a.y , s.b.y )                 && bot.x >= max( s.a.x , s.b.x ) )            ok = true ;        if( ok )            puts( "T" ) ;        else            puts( "F" ) ;    }    return 0;}

POJ 2074 Line of Sight(直线交点+区间并)

题意:

在房子里看路的视线可能会被障碍物挡住,问从这条路上能看到完整路的最大长度。

思路:

盲区范围:房子的左端点与障碍物的右端点所成直线与路的交点p1,房子的右端点与障碍物的左端点所成直线与路的交点p2.盲区即为p2到p1的范围。
求出所有的盲区范围,把所有盲区线段按左端点的x坐标升序排序,然后从左到右扫一遍,维护i之前所有线段的最右端的x坐标last。如果第i个盲区的左端点大于last,那么last到i的左端点的这片区域都是不被覆盖的。扫描每个线段时更新last。
注意障碍物不一定在路与房子之间。

代码:

/* * @author FreeWifi_novicer * language : C++/C */#include<cstdio>#include<iostream>#include<cstring>#include<cstdlib>#include<cmath>#include<algorithm>#include<string>#include<map>#include<set>#include<vector>#include<queue>using namespace std;#define clr( x , y ) memset(x,y,sizeof(x))#define cls( x ) memset(x,0,sizeof(x))#define mp make_pair#define pb push_backtypedef long long lint;typedef long long ll;typedef long long LL;const double pi = acos( -1.0 ) ;const double eps = 1e-8 ;inline double sqr( double x ) { return x * x ; } inline int cmp( double x ){    if( fabs(x) < eps ) return 0 ;    if( x > 0 ) return 1 ;    return -1 ;}struct Point{    double x , y ;    Point(){} ;    Point( double a , double b ):x(a) , y(b){}    void input(){        scanf( "%lf%lf" , &x , &y ) ;    }    double norm(){        return sqrt( sqr( x ) + sqr( y ) ) ;    }    friend Point operator + ( const Point &a , const Point &b ) { return Point( a.x + b.x , a.y + b.y ) ; }    friend Point operator - ( const Point &a , const Point &b ) { return Point( a.x - b.x , a.y - b.y ) ; }    friend Point operator * ( const Point &a , const double &b ) { return Point( a.x * b , a.y * b ) ; }    friend Point operator * ( const double &a , const Point &b ) { return Point( b.x * a , b.y * a ) ; }    friend Point operator / ( const Point &a , const double &b ) { return Point( a.x / b , a.y / b ) ; }    friend bool operator == ( const Point &a , const Point &b ) { return cmp( a.x - b.x ) == 0 && cmp( a.y - b.y ) == 0 ; }};typedef Point Vector ;double dot( const Point &a , const Point &b ){ return a.x * b.x + a.y * b.y ; }double det( const Point &a , const Point &b ){ return a.x * b.y - a.y * b.x ; }double dist( const Point &a , const Point &b ){ return ( a - b ).norm() ; }struct Line{    Point a , b ;    Line(){}    Line( Point x , Point y ): a(x) , b(y){}};Point line_make_point( Line a , Line b ){    double s1 = det( a.a - b.a , b.b - b.a ) ;    double s2 = det( a.b - b.a , b.b - b.a ) ;    Point res = ( s1 * a.b - s2 * a.a ) / ( s1 - s2 ) ;    return res ;}bool cmp1( Line l1 , Line l2 ){    if( cmp( l1.a.x - l2.a.x ) != 0 )        return l1.a.x < l2.a.x ;    return l1.b.x < l2.b.x ;}vector<Line>light ;int main(){    //freopen("input.txt","r",stdin);    double x1 , x2 , y ;    while( cin >> x1 >> x2 >> y ){        if( !x1 && !x2 && !y ) break ;        light.clear() ;        if( x1 > x2 ) swap( x1 , x2 ) ;        Line h( Point( x1 , y ) , Point( x2 , y ) ) ;        cin >> x1 >> x2 >> y ;        Line l( Point( x1 , y ) , Point( x2 , y ) ) ;        int n ;        cin >> n ;        if( n == 0 ){            printf( "%.2f\n" , x2 - x1 ) ;            continue ;        }        for( int i = 1 ; i <= n ; i++ ){            scanf( "%lf%lf%lf" , &x1 , &x2 , &y ) ;            if( y > h.a.y - eps || y < l.a.y + eps ) continue ;            if( x1 > x2 ) swap( x1 , x2 ) ;            Line H( Point( x1 , y ) , Point( x2 , y ) ) ;            Point p1 = line_make_point( Line( h.a , H.b ) , l ) ;            if( p1.x < l.a.x ) p1.x = l.a.x ;            if( p1.x > l.b.x ) p1.x = l.b.x ;            Point p2 = line_make_point( Line( h.b , H.a ) , l ) ;            if( p2.x < l.a.x ) p2.x = l.a.x ;            if( p2.x > l.b.x ) p2.x = l.b.x ;            if( cmp( p1.x - p2.x ) == 0 ) continue ;            else{                light.pb( Line( p2 , p1 ) ) ;            }        }        sort( light.begin() , light.end() , cmp1 ) ;        int s = light.size() ;        if( light.empty() ){            printf( "%.2f\n" , l.b.x - l.a.x ) ;            continue ;        }        double ans = 0 , last = 0 ;         for( int i = 0 ; i < s ; i++ ){            if( light[i].a.x > last ){                ans = max( ans , light[i].a.x - last ) ;                last = light[i].b.x ;            }            else {                last = max( last , light[i].b.x ) ;            }        }        ans = max( ans , l.b.x - last ) ;        if( !cmp( ans ) )            puts( "No View" ) ;        else            printf( "%.2f\n" , ans ) ;    }    return 0;}
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 孩子字写得难看怎么办 孩子上一年级不认识字怎么办 二年级孩子语文差怎么办 孩子二年级语文成绩差怎么办 孩子小学二年级语文差怎么办 二年级孩子语文理解能力差怎么办 深圳租房被坑了怎么办 小鸣单车押金退不了怎么办 联想台式一体机忘记密码怎么办 ps直线工具变成箭头了怎么办 笔记本图形处理速度慢怎么办 微信语音发不出去怎么办 ps里的图层锁定怎么办 ps图层丢失了怎么办 PS标题画面太小怎么办 轮胎蹭掉一块皮怎么办 吃香蕉吃的胃难受怎么办 qq糖卡在喉咙里怎么办 头发上粘到了qq糖怎么办 老房子土墙掉土怎么办 速写画的太慢怎么办 艺术生文化课没过线怎么办 5岁儿童坐飞机忘带证件怎么办 儿童坐飞机没带证件怎么办 儿童坐飞机没带户口本怎么办 儿童坐飞机没有带户口本怎么办 刚打蜡的车下雨怎么办 飞机票不能退票不能改签怎么办 深圳航空买机票姓名错了怎么办 大众cc打不着火怎么办 手上扎了仙人掌刺怎么办 pscs5界面字体太小怎么办 儿童做飞机没带户口本怎么办 黑户口想做飞机怎么办 宝宝坐飞机忘记带证件怎么办 值机柜台关闭了怎么办 值机迟到几分钟怎么办 婴儿坐飞机没带证件怎么办 飞机票买了一天降价1000怎么办 社保卡磁性没了怎么办 社保卡民族错了怎么办