poj 2318 叉积(附带kuangbin关于点的叉积,点积,点绕原点旋转,两直线关系模版)
转自 http://www.cnblogs.com/kuangbin/p/3188484.html
kuangbin关于点的叉积,点积,点绕原点旋转,两直线关系模版:
int sgn(double x){ if(fabs(x) < eps) return 0; if(x < 0) return -1; else return 1; } struct Point{ int x,y; Point() { } Point(double _x,double _y){ x = _x,y = _y; } Point operator - (const Point &b) const{ //相对坐标 return Point(x - b.x,y - b.y); } double operator ^(const Point &b)const{//叉积 return x*b.y - y*b.x; } double operator *(const Point &b)const{//点积 return x*b.x + y*b.y; } void transXY(double B){ double tx = x,ty = y; x = tx*cos(B) - ty*sin(B); y = tx*sin(B) + ty*cos(B); } }; struct Line{ Point s,e; Line() { } Line (Point _s,Point _e){ s = _s,e = _e; } //两直线相交求交点 //第一个值为0表示直线重合,为1表示平行,为2是相交 //只有第一个值为2时交点才有意义 pair<int,Point> operator &(const Line &b) const{ Point res = s; if(sgn((s-e)^(b.s-b.e)) == 0){ if(sgn((s-b.e)^(b.s-b.e)) == 0) return make_pair(0,res);//重合 else return make_pair(1,res); } double t = ((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e)); res.x += (e.x-s.x)*t; res.y += (e.y-s.y)*t; return make_pair(2,res); } };
就是给了m个点,落在n+1个区域中,问各个区域有多少个点。
就是利用叉积去判断点在线段的哪一侧,可以二分去做,比较快。
1 #include <cstdio> 2 #include <cstring> 3 #include <vector> 4 #include <algorithm> 5 #include <iostream> 6 #include <map> 7 #include <queue> 8 #include <stack> 9 #include <cmath> 10 //#pragma comment(linker, "/STACK:102400000,102400000") 11 using namespace std; 12 #define PF(x) cout << "debug: " << x << " "; 13 #define EL cout << endl; 14 #define PC(x) puts(x); 15 typedef long long ll; 16 #define CLR(x, v) sizeof (x, v, sizeof(x)) 17 using namespace std; 18 const int INF = 0x5f5f5f5f; 19 const int N= 2e5 + 10; 20 const int mod=1e9 + 7; 21 const int maxn = 5e3 + 10; 22 const double eps = 1e-8; 23 const double PI = acos(-1.0); 24 int n,m,ans[maxn]; 25 int sgn(double x){ 26 if(fabs(x) < eps) return 0; 27 if(x < 0) return -1; 28 else return 1; 29 30 } 31 struct Point{ 32 int x,y; 33 Point() { } 34 Point(double _x,double _y){ 35 x = _x,y = _y; 36 } 37 Point operator - (const Point &b) const{ //相对坐标 38 return Point(x - b.x,y - b.y); 39 } 40 double operator ^(const Point &b)const{//叉积 41 return x*b.y - y*b.x; 42 } 43 double operator *(const Point &b)const{//点积 44 return x*b.x + y*b.y; 45 } 46 void transXY(double B){ 47 double tx = x,ty = y; 48 x = tx*cos(B) - ty*sin(B); 49 y = tx*sin(B) + ty*cos(B); 50 } 51 }; 52 struct Line{ 53 Point s,e; 54 Line() { } 55 Line (Point _s,Point _e){ 56 s = _s,e = _e; 57 } 58 //两直线相交求交点 59 //第一个值为0表示直线重合,为1表示平行,为2是相交 60 //只有第一个值为2时交点才有意义 61 pair<int,Point> operator &(const Line &b) const{ 62 Point res = s; 63 if(sgn((s-e)^(b.s-b.e)) == 0){ 64 if(sgn((s-b.e)^(b.s-b.e)) == 0) 65 return make_pair(0,res);//重合 66 else 67 return make_pair(1,res); 68 } 69 double t = ((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e)); 70 res.x += (e.x-s.x)*t; 71 res.y += (e.y-s.y)*t; 72 return make_pair(2,res); 73 } 74 }; 75 int pmul(Point a,Point b,Point c){ 76 return (b-a) ^ (c-a); 77 } 78 int main() 79 { 80 // freopen("in.txt","r",stdin); 81 while(~scanf("%d",&n)){ 82 if(n == 0) 83 break; 84 memset(ans,0,sizeof(ans)); 85 double x1,y1,x2,y2; 86 scanf("%d%lf%lf%lf%lf",&m,&x1,&y1,&x2,&y2); 87 Line line[maxn]; 88 int ui,li; 89 for(int i = 0;i < n;i++){ 90 scanf("%d%d",&ui,&li); 91 line[i] = Line(Point(ui,y1),Point(li,y2)); 92 } 93 line[n] = Line(Point(x2,y1),Point(x2,y2)); 94 while(m--){ 95 int x,y; 96 scanf("%d%d",&x,&y); 97 Point p = Point(x,y); 98 int tmp; 99 int l = 0,r = n; 100 while(l <= r){ 101 int mid = (l+r)>>1; 102 if(pmul(p,line[mid].s,line[mid].e) < 0){ 103 tmp = mid; 104 r = mid - 1; 105 } 106 else l = mid + 1; 107 } 108 ans[tmp]++; 109 } 110 for(int i = 0;i <= n;i++) 111 printf("%d: %d\n",i,ans[i]); 112 cout<<endl; 113 } 114 return 0; 115 }