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"); } }
时间: 2024-10-05 19:19:41