SGU 253 Theodore Roosevelt 快速判断点是否在凸包内
http://acm.sgu.ru/problem.php?contest=0&problem=253
题意简单易懂...给你n个点的凸包(经测试已经是极角序)...判断m个点是否在凸包内...数量>=k就输出YES
46ms过的...貌似数据很水...但暴力判断每个点复杂度O(n*m)肯定T了...
二分可以优化到O(mlogn) -----该算法受到AC巨巨的启发:http://hi.baidu.com/aekdycoin/item/2d54f9c0fef55457ad00efd6
把凸包分成n-2个三角形...然后二分点是否在这些三角形内即可...注意一下只有三个点的情况即可
/********************* Template ************************/ #include <set> #include <map> #include <list> #include <cmath> #include <ctime> #include <deque> #include <queue> #include <stack> #include <bitset> #include <cstdio> #include <string> #include <vector> #include <cassert> #include <cstdlib> #include <cstring> #include <sstream> #include <fstream> #include <numeric> #include <iomanip> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define EPS 1e-8 #define MAXN 100005 #define MOD (int)1e9+7 #define PI acos(-1.0) #define INF ((1LL)<<50) #define max(a,b) ((a) > (b) ? (a) : (b)) #define min(a,b) ((a) < (b) ? (a) : (b)) #define max3(a,b,c) (max(max(a,b),c)) #define min3(a,b,c) (min(min(a,b),c)) #define BUG cout<<"BUG! "<<endl #define LINE cout<<"------------------"<<endl #define L(t) (t << 1) #define R(t) (t << 1 | 1) #define Mid(a,b) ((a + b) >> 1) #define lowbit(a) (a & -a) #define FIN freopen("in.txt","r",stdin) #pragma comment (linker,"/STACK:102400000,102400000") // typedef long long LL; // typedef unsigned long long ULL; // typedef __int64 LL; // typedef unisigned __int64 ULL; // int gcd(int a,int b){ return b?gcd(b,a%b):a; } // int lcm(int a,int b){ return a*b/gcd(a,b); } /********************* F ************************/ struct POINT{ double x,y; POINT(double _x = 0, double _y = 0):x(_x),y(_y){}; void show(){ cout<<x<<" "<<y<<endl; } }; POINT p[MAXN],wp[MAXN]; double multiply(POINT sp,POINT ep,POINT op){ //叉积 return (sp.x-op.x) * (ep.y-op.y) - (ep.x-op.x) * (sp.y-op.y); } bool onseg(POINT a,POINT s,POINT e){ // 判断点是否在线段上 if(multiply(a,s,e) == 0 && a.x <= max(s.x,e.x) && a.x >= min(s.x,e.x) && a.y <= max(s.y,e.y) && a.y >= min(s.y,e.y)) return true; return false; } bool inside(POINT pp,POINT sp,POINT ep,POINT op){ //判断点pp是否在三角形中(极角序) if(onseg(pp,sp,ep) || onseg(pp,sp,op) || onseg(pp,ep,op)) //如果在三角形上 return true; if(multiply(sp,ep,pp) > 0 && multiply(ep,op,pp) > 0 && multiply(sp,op,pp) < 0) //如果在三角形内 return true; return false; } bool bsearch(POINT a,int len){ //二分所构造的三角形 int l = 1,r = len,m; while(l < r){ m = (l + r) / 2; if(inside(a,p[0],p[m],p[m+1]) == true) return true; if(multiply(p[0],p[m],a) >= 0 && multiply(p[0],p[m+1],a) <= 0 && multiply(p[m],p[m+1],a) < 0) return false; if(multiply(p[0],p[m],a) > 0 && multiply(p[0],p[m+1],a) > 0) l = m + 1; else r = m; } return false; } int main() { //freopen("in.txt","r",stdin); int n,m,k,tmp = 0,cnt = 0; scanf("%d%d%d",&n,&m,&k); for(int i = 0 ; i < n ; i++) scanf("%lf%lf",&p[i].x,&p[i].y); p[n] = p[0]; for(int i = 0 ; i < m ; i++){ scanf("%lf%lf",&wp[i].x,&wp[i].y); if(bsearch(wp[i],n-1) == true) cnt++; } if(cnt >= k) printf("YES\n"); else printf("NO\n"); return 0; }