POJ 2318 TOYS 利用叉积判断点在线段的那一侧
题意:给定n(<=5000)条线段,把一个矩阵分成了n+1分了,有m个玩具,放在为位置是(x,y)。现在要问第几个位置上有多少个玩具。
思路:叉积,线段p1p2,记玩具为p0,那么如果(p1p2 ^ p1p0) (记得不能搞反顺序,不同的),如果他们的叉积是小于0,那么就是在线段的左边,否则右边。所以,可以用二分找,如果在mid的左边,end=mid-1 否则begin=mid+1。结束的begin,就是第一条在点右边的线段
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; #include <iostream> #include <sstream> #include <vector> #include <set> #include <map> #include <queue> #include <string> const int maxn = 5000+20; struct coor { double x,y; coor(){} coor(double xx,double yy):x(xx),y(yy){} double operator ^(coor rhs) const //计算叉积(向量积) { return x*rhs.y - y*rhs.x; } coor operator -(coor rhs) const //坐标相减,a-b得到向量ba { return coor(x-rhs.x,y-rhs.y); } double operator *(coor rhs) const //数量积 { return x*rhs.x + y*rhs.y; } }; struct Line { coor point1,point2; Line(){} Line(coor xx,coor yy):point1(xx),point2(yy){} }a[maxn]; int n,m; double xx1,yy1,xx2,yy2; int cnt[maxn]; int calc (coor t) { int begin=1,end=n; while(begin<=end) { int mid = (begin+end)/2; coor ff1 = a[mid].point2 - a[mid].point1; //point1是起点 coor ff2 = t - a[mid].point1; if ((ff1^ff2) < 0) { end=mid-1; } else begin=mid+1; } return begin; } void work () { memset(cnt,0,sizeof cnt); for (int i=1;i<=n;++i) { double xxx1,xxx2; scanf("%lf%lf",&xxx1,&xxx2); a[i].point1.x=xxx1, a[i].point1.y=yy1; a[i].point2.x=xxx2, a[i].point2.y=yy2; } for (int i=1;i<=m;++i) { coor t; scanf("%lf%lf",&t.x,&t.y); cnt[calc(t)-1]++; //printf ("%d\n",calc(t)); } for (int i=0;i<=n;++i) { printf ("%d: %d\n",i,cnt[i]); } return ; } int main() { #ifdef local freopen("data.txt","r",stdin); #endif //while(~scanf("%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y) && (a.x+a.y+b.x+b.y)) work(); while(scanf("%d%d%lf%lf%lf%lf",&n,&m,&xx1,&yy1,&xx2,&yy2)!=EOF && n) { work(); printf ("\n"); } return 0; }
既然选择了远方,就要风雨兼程~
posted on 2016-08-10 21:01 stupid_one 阅读(270) 评论(0) 编辑 收藏 举报