POJ 2318/2398 叉积性质
题意:给出n条线将一块区域分成n+1块空间,再给出m个点,询问这些点在哪个空间里。
思路:由于只要求相对位置关系,而对具体位置不关心,那么易使用叉积性质得到相对位置关系(左侧/右侧),再因为是简单几何线段不相较,即有序分布,那么在求在哪个区间时可以先对所有线段根据x坐标排序,使用二分减少复杂度。
/** @Date : 2017-07-11 11:05:59 * @FileName: POJ 2318 叉积性质.cpp * @Platform: Windows * @Author : Lweleth (SoungEarlf@gmail.com) * @Link : https://github.com/ * @Version : $Id$ */ #include <stdio.h> #include <iostream> #include <string.h> #include <algorithm> #include <utility> #include <vector> #include <map> #include <set> #include <string> #include <stack> #include <queue> //#include <bits/stdc++.h> #define LL long long #define PII pair #define MP(x, y) make_pair((x),(y)) #define fi first #define se second #define PB(x) push_back((x)) #define MMG(x) memset((x), -1,sizeof(x)) #define MMF(x) memset((x),0,sizeof(x)) #define MMI(x) memset((x), INF, sizeof(x)) using namespace std; const int INF = 0x3f3f3f3f; const int N = 1e5+20; const double eps = 1e-8; struct Point { int x, y; Point(){} Point(int xx, int yy){x = xx, y = yy;} Point operator -(const Point &b) const { return Point(x - b.x, y - b.y); } int operator *(const Point &b) const { return x * b.x + y * b.y; } }; int cross(Point a, Point b) { return a.x * b.y - a.y * b.x; } struct Line { Point s, t; Line(){} Line(Point ss, Point tt){s = ss, t = tt;} }; int JudegeCross(Point p0, Point p1, Point p2) { return cross(p1 - p0, p2 - p0); } Line li[N]; int ans[N]; int vis[N]; int cmp(Line a, Line b) { return a.s.x < b.s.x; } int main() { int n, m, x1, x2, y1, y2; while(~scanf("%d", &n) && n) { MMF(ans); MMF(vis); scanf("%d%d%d%d%d", &m, &x1, &y1, &x2, &y2); for(int i = 0; i < n; i++) { int s, t; scanf("%d%d", &s, &t); li[i] = Line(Point(s, y1), Point(t, y2)); } li[n] = Line(Point(x2, y1), Point(x2, y2)); sort(li, li + n + 1, cmp); while(m--) { int x, y; scanf("%d%d", &x, &y); Point p = Point(x, y); int l = 0, r = n; int pos = 0; while(l <= r) { int mid = (l + r) >> 1; if(JudegeCross(p, li[mid].s, li[mid].t) < 0) { pos = mid; r = mid - 1; } else l = mid + 1; } ans[pos]++; } printf("Box\n"); for(int i = 0; i <= n; i++) if(ans[i]) vis[ans[i]]++; for(int i = 1; i <= n; i++) if(vis[i]) printf("%d: %d\n", i, vis[i]); } return 0; }
/** @Date : 2017-07-11 11:05:59 * @FileName: POJ 2318 叉积性质.cpp * @Platform: Windows * @Author : Lweleth (SoungEarlf@gmail.com) * @Link : https://github.com/ * @Version : $Id$ */ #include <stdio.h> #include <iostream> #include <string.h> #include <algorithm> #include <utility> #include <vector> #include <map> #include <set> #include <string> #include <stack> #include <queue> //#include <bits/stdc++.h> #define LL long long #define PII pair #define MP(x, y) make_pair((x),(y)) #define fi first #define se second #define PB(x) push_back((x)) #define MMG(x) memset((x), -1,sizeof(x)) #define MMF(x) memset((x),0,sizeof(x)) #define MMI(x) memset((x), INF, sizeof(x)) using namespace std; const int INF = 0x3f3f3f3f; const int N = 1e5+20; const double eps = 1e-8; struct Point { int x, y; Point(){} Point(int xx, int yy){x = xx, y = yy;} Point operator -(const Point &b) const { return Point(x - b.x, y - b.y); } int operator *(const Point &b) const { return x * b.x + y * b.y; } }; int cross(Point a, Point b) { return a.x * b.y - a.y * b.x; } struct Line { Point s, t; Line(){} Line(Point ss, Point tt){s = ss, t = tt;} }; int JudegeCross(Point p0, Point p1, Point p2) { return cross(p1 - p0, p2 - p0); } Line li[N]; int ans[N]; int main() { int n, m, x1, x2, y1, y2; while(~scanf("%d", &n) && n) { MMF(ans); scanf("%d%d%d%d%d", &m, &x1, &y1, &x2, &y2); for(int i = 0; i < n; i++) { int s, t; scanf("%d%d", &s, &t); li[i] = Line(Point(s, y1), Point(t, y2)); } li[n] = Line(Point(x2, y1), Point(x2, y2)); while(m--) { int x, y; scanf("%d%d", &x, &y); Point p = Point(x, y); int l = 0, r = n; int pos = 0; while(l <= r) { int mid = (l + r) >> 1; if(JudegeCross(p, li[mid].s, li[mid].t) < 0) { pos = mid; r = mid - 1; } else l = mid + 1; } ans[pos]++; } for(int i = 0; i <= n; i++) { printf("%d: %d\n", i, ans[i]); } printf("\n"); } return 0; }