题目链接:http://poj.org/problem?id=2318
题意大致是给了m个玩具,这m个玩具在n+1个盒子里。坐标给定,求每个盒子里有多少个玩具。
简单考虑就是判断点在线段的哪一侧,二分+判断即可。
方法1:在BJTU集训队课件上看到的:
检查线段p1p3是在线段p1p2的顺时针方向还是逆时针方向
计算(p3–p1)x(p2–p1)
方法2:学堂在线上邓俊辉老师开的计算几何课程讲了一个用行列式的方法,具体证明可以参考计算几何这门课程。
判断p2点在直线p1p3的左侧还是右侧:
|p1.x p1.y 1|
|p3.x p3.y 1|
|p2.x p2.y 1|
泛型在调用的时候特别麻烦,回头改成用宏替换好了。代码如下:
1 #include <algorithm> 2 #include <iostream> 3 #include <iomanip> 4 #include <cstring> 5 #include <climits> 6 #include <complex> 7 #include <fstream> 8 #include <cassert> 9 #include <cstdio> 10 #include <bitset> 11 #include <vector> 12 #include <deque> 13 #include <queue> 14 #include <stack> 15 #include <ctime> 16 #include <set> 17 #include <map> 18 #include <cmath> 19 20 using namespace std; 21 22 template<typename pp> 23 struct Point { 24 pp x; 25 pp y; 26 Point(){} 27 Point(pp xx, pp yy) : x(xx), y(yy) {} 28 }; 29 30 31 template<typename pp> 32 struct Line { 33 Point<pp> u; 34 Point<pp> v; 35 Line() {} 36 Line(Point<pp> uu, Point<pp> vv) : u(uu), v(vv) {} 37 }; 38 39 /* 40 检查线段p1p3是在线段p1p2的顺时针方向还是逆时针方向 41 计算(p3–p1)x(p2–p1) 42 */ 43 template<typename pp> 44 pp direction1(Point<pp> p1, Point<pp> p2, Point<pp> p3) { // >0右拐 <0左拐 45 return (p3.x-p1.x)*(p2.y-p1.y)-(p2.x-p1.x)*(p3.y-p1.y); 46 } 47 48 /* 49 |p1.x p1.y 1| 50 |p3.x p3.y 1| 51 |p2.x p2.y 1| 52 */ 53 template<typename pp> 54 pp direction2(Point<pp> p1, Point<pp> p2, Point<pp> p3) { // >0右拐 <0左拐 55 return (p1.x*p3.y+p1.y*p2.x+p3.x*p2.y)-(p2.x*p3.y+p1.x*p2.y+p1.y*p3.x); 56 } 57 58 59 const int maxn = 6666; 60 int n, m; 61 int ex1, ey1, ex2, ey2; 62 Line<int> line[maxn]; 63 int ans[maxn]; 64 65 int main() { 66 // freopen("in", "r", stdin); 67 int flg = 1; 68 while(~scanf("%d", &n) && n) { 69 memset(ans, 0, sizeof(ans)); 70 scanf("%d %d %d %d %d", &m, &ex1, &ey1, &ex2, &ey2); 71 int Ui, Li; 72 for(int i = 0; i < n; i++) { 73 scanf("%d %d", &Ui, &Li); 74 line[i] = Line<int>(Point<int>(Ui, ey1), Point<int>(Li, ey2)); 75 } 76 line[n] = Line<int>(Point<int>(ex2, ey1), Point<int>(ex2, ey2)); 77 int x, y; 78 Point<int> p; 79 while(m--) { 80 scanf("%d %d", &x, &y); 81 p = Point<int>(x, y); 82 int ll = 0, rr = n; 83 int tmp; 84 while(ll <= rr) { 85 int mm = (ll + rr) >> 1; 86 if(direction1<int>(p, line[mm].u, line[mm].v) > 0) { 87 tmp = mm; 88 rr = mm - 1; 89 } 90 else ll = mm + 1; 91 } 92 ans[tmp]++; 93 } 94 flg ? flg = 0 : printf(" "); 95 for(int i = 0; i <= n; i++) { 96 printf("%d: %d ", i, ans[i]); 97 } 98 } 99 return 0; 100 }