SGU 253. Theodore Roosevelt

来源:互联网 发布:薛定谔的猫 知乎 编辑:程序博客网 时间:2024/05/19 13:43

题目:http://acm.sgu.ru/problem.php?contest=0&problem=253

本题要求在一个给定凸包,一些点有几个是在凸包内的(包括边界)。

以前判断某一点是否在多边形内,可以叉积依次求面积的方法,但是每次查询耗时O(n)。

所以这里提一种每次查询只需要O(lgn)的解法。

就是先按极角排序,然后二分求给定点的极角范围,叉积计算进行求解。

一开始我的线段拐向求反了,导致wa on test 5。一定要小心啊。

而且swap写的一开始也有问题,谢学弟帮我排bug。二分法的临界仍然需要熟练掌握。是在担心写错,就直接用STL upper_bound吧。不要自己写了。

http://www.cnblogs.com/cobbliu/archive/2012/05/21/2512249.html

#include <iostream>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <math.h>#include <algorithm>using namespace std;const double eps = 1e-8;struct Point{    long long  x;    long long y;    double angle;    long long dis;    Point() {}    Point(long long _x,long long _y):x(_x),y(_y) {}    friend Point operator + (Point a,Point b)    {        return Point(a.x+b.x , a.y+b.y);    }    friend Point operator - (Point a,Point b)    {        return Point(a.x-b.x , a.y-b.y);    }};int dcmp(double x){    if(fabs(x)<eps)    {        return 0;    }    return x>0?1:-1;}double det(Point a,Point b){    return a.x*b.y-a.y*b.x;}double det(Point a,Point b,Point o){    return det(a-o,b-o);}double det(Point a,Point b,Point c,Point d){    return det(b-a,d-c);}Point p[100005];bool cmp(Point a,Point b){    return dcmp(a.angle-b.angle)<0 || (dcmp(a.angle - b.angle)==0 && a.dis <b.dis);}void swap(Point &a,Point &b){    Point c = b;    b = a;    a = c;}int main(){#ifndef ONLINE_JUDGE    freopen("in.txt","r",stdin);#endif    int n,m,k;    while(scanf(" %d %d %d",&n,&m,&k)!=EOF)    {        Point le;        int le_num = 0;        for(int i=0;i<n;i++)        {            scanf(" %lld %lld",&p[i].x,&p[i].y);            //求最下左点            if(i==0)            {                le.x = p[0].x;                le.y = p[0].y;                le_num = 0;            }            else            {                if(p[i].y<le.y || (p[i].y == le.y && p[i].x < le.x))                {                    le = p[i];                    le_num = i;                }            }        }        swap(p[0],p[le_num]);        for(int i=1;i<n;i++)        {            p[i].angle = atan2(p[i].y - p[0].y,p[i].x - p[0].x);            p[i].dis = (p[i].x - p[0].x)*(p[i].x - p[0].x) + (p[i].y - p[0].y)*(p[i].y - p[0].y);        }        sort(p+1,p+n,cmp);        int x,y;        int num = 0;        for(int i=0;i<m;i++)        {            Point temp;            scanf(" %lld %lld",&temp.x,&temp.y);            if(temp.x == p[0].x && temp.y == p[0].y)            {                num++;            }            else            {                temp.angle = atan2(temp.y-p[0].y,temp.x-p[0].x);                int low = 1;                int high = n-1;                if(dcmp(temp.angle - p[high].angle)>0 || dcmp(temp.angle - p[low].angle)<0)                {                    continue;                }                int pos = 1;                //求upper_bound                while(low<high)                {                    int mid = (low + high)/2;                    if( p[mid].angle <= temp.angle)                    {                        low = mid + 1;                        pos = low;                    }                    else                    {                       high = mid;                       pos = high;                    }                }                if(pos == n)                {                    pos--;                }                if(det(temp,p[pos -1],p[pos])>=0)                {                    num++;                }            }        }        if(num>=k)        {            printf("YES\n");        }        else        {            printf("NO\n");        }    }    return 0;}
参考:http://hi.baidu.com/aekdycoin/item/2d54f9c0fef55457ad00efd6

原创粉丝点击