解题思路:以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)
*/