判点是否在凸包内(2分极角序)
判点是否在凸包内(二分极角序)
判点是否在凸包内(二分极角序)
解题思路:以p[1]为基点,将所有的点按极角序排好,然后共线都点都去掉(当然,这个处理还是有点小麻烦)。如果我们将所有的点跟p[1]相连,可以将凸包划分成n-2个扇形区。那么,我们可二分出要判断的点所在的扇形区,然后用差积判是在内侧还是外侧。
代码:
#include <stdio.h> #include <string.h> #include <algorithm> #include <map> #include <math.h> #include <queue> #include <vector> #include <string> #include <iostream> #include <stdlib.h> #include <time.h> #define lowbit(x) (x&(-x)) #define ll __int64 #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 #define ls son[0][rt] #define rs son[1][rt] #define new_edge(a,b,c) edge[tot].t = b , edge[tot].v = c , edge[tot].next = head[a] , head[a] = tot ++ using namespace std; struct Point { double x , y ; Point ( double _x = 0 , double _y = 0 ) : x(_x) , y(_y) {} void print () { printf ( "%.2lf,%.2lf\n" , x , y ) ; } } ; double cross ( Point o , Point a , Point b ) { Point u = Point ( a.x - o.x , a.y - o.y ) ; Point v = Point ( b.x - o.x , b.y - o.y ) ; return ( u.x * v.y - u.y * v.x ) ; } Point p[1111] ; double length ( Point a , Point b ) { return (b.x-a.x) * (b.x-a.x) + (b.y-a.y) * (b.y-a.y) ; } bool cmp ( Point i , Point j ) { if ( cross ( p[1] , i , j ) == 0 ) return ( length ( p[1] , i ) < length ( p[1] , j ) ) ; return ( cross ( p[1] , i , j ) > 0 ) ; } int bin ( Point key , int r ) { int l = 2 ; while ( l <= r ) { int m = ( l + r ) >> 1 ; if ( cross ( p[1] , p[m] , key ) <= 0 ) r = m - 1 ; else l = m + 1 ; } return l ; } int vis[1111] ; int main() { int n , i , j , k , l , m ; // freopen ( "a.txt" , "r" , stdin ) ; //freopen ( "b.txt" , "w" , stdout ) ; while ( scanf ( "%d" , &n ) != EOF ) { for ( i = 1 ; i <= n ; i ++ ) { getchar () ; scanf ( "(%lf,%lf)" , &p[i].x , &p[i].y ) ; } memset ( vis , 0 , sizeof ( vis ) ) ; sort ( p + 2 , p + n + 1 , cmp ) ; j = n - 1 ; while ( cross ( p[1] , p[j] , p[n] ) == 0 ) vis[j] = 1 , j -- ; int tot = 1 ; for ( i = 2 ; i <= n ; i ++ ) if ( !vis[i] ) p[++tot] = p[i] ; n = tot ; tot = 2 ; for ( i = 3 ; i <= n ; i ++ ) { if ( cross ( p[tot-1] , p[tot] , p[i] ) == 0 ) p[tot] = p[i] ; else p[++tot] = p[i] ; } scanf ( "%d" , &m ) ; while ( m -- ) { double x , y ; getchar () ; scanf ( "(%lf,%lf)" , &x , &y ) ; Point u = Point (x,y) ; k = bin ( u , tot ) ; if ( k > tot ) puts ( "No" ) ; else if ( k == 2 ) { if ( cross (p[1] , p[2] , u) > 0 ) puts ( "Yes" ) ; else if ( cross (p[1] , p[2] , u ) == 0 ) { if ( length ( p[1] , p[2] ) < length ( p[1] , u ) ) puts ( "No" ) ; else puts ( "Yes" ) ; } else puts ( "No" ) ; } else if ( cross (p[k-1] , p[k] , u) >= 0 ) puts ( "Yes" ) ; else puts ( "No" ) ; } } return 0; } /* 7 (-55,0) (-44,11) (-22,33) (11,22) (0,-22) (-22,-33) (-44,-22) 1000 (-22,-66) */