Hrbustoj 1429 二分+计算几何

http://www.bubuko.com/infodetail-1121744.html 在这个上面学习了方法 如果要判断巨量的点 就应该使用二分法

思路是先从a[1] a[n] a[2]来判断是否可能在图形内 如果这个都通不过就不用再判断下边的了 

然后从 2 到 n 开始二分 确定两个相邻向量 使寻找点必在这两个向量的夹角里

然后就是点是否在三角形内了 由于已经判断了两条边了 最后只判断第三条即可

一开始 二分的while条件写的是r-l!=0 最后得到的效果是 点必定在r l向量的夹角内

然而超时 很不理解QAQ

后来学习了网上的办法 设定条件l<r 这样最后得到的l其实是等于r的 点在l l-1的夹角内

学习的方法里提到了一点 位运算比乘除运算快非常多

分别尝试了一下 位运算 485ms 正常乘除 541ms 

自己写的代码

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<math.h>
using namespace std;
struct point
{
    double x,y;
};
double cross(point a,point b,point c)
{
    return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
}
int main(){
int n;
while(~scanf("%d",&n))
{
    point a[n+1];
    for(int i=1;i<=n;i++)
    {
        scanf("%lf%lf",&a[i].x,&a[i].y);
    }
    bool ok=true;
    int m;
    scanf("%d",&m);
    point p[m];
    for(int i=0;i<m;i++)
    {
        scanf("%lf%lf",&p[i].x,&p[i].y);

    }
    for(int i=0;i<m;i++)
    {
        if(cross(a[1],p[i],a[2])<=0||cross(a[1],a[n],p[i])<=0)
        {
            ok=false;
            break;
        }
        int l=2;
        int r=n;
        int m;
        while(l<r)
        {
            m=(r+l)/2;/// m=(r+l)>>1 更快一些
            if(cross(a[1],p[i],a[m])<=0)
            {
                r=m;
            }
            else l=m+1;
        }
        if(cross(a[l],p[i],a[l-1])>=0) 
        {
            ok=false;
            break;
        }
    }

    if(ok==true)
        printf("YES\n");
    else printf("NO\n");
}
}

  

posted @ 2016-02-21 01:57  天翎月  阅读(360)  评论(0编辑  收藏  举报