Kiểm tra điểm nằm trong đa giác
Trường hợp kiểm tra trong đa giác lồi
Đề bài: https://oj.vnoi.info/problem/meterain
Duyệt từng cạnh - \(O(N)\)
#include <bits/stdc++.h>
#define Point Vector
using namespace std;
struct Vector {
int x, y;
Vector() { x = y = 0; }
Vector(int xx, int yy) {
x = xx; y = yy;
}
Vector operator - (const Vector &v) const {
return Vector(x-v.x,y-v.y);
}
long long operator % (const Vector &v) const {
return 1LL * x * v.y - 1LL * y * v.x;
}
friend bool CCW(const Point &a, const Point &b, const Point &c) {
return (b-a) % (c-b) > 0;
}
friend istream& operator >> (istream&is, Vector &v) {
is >> v.x >> v.y;
return is;
}
};
const int N = 5007;
int polySize, numPoint;
Point polygon[N];
bool inPolygon(const Point &p) {
for (int i = 0; i < polySize; ++i) {
if (!CCW(polygon[i],polygon[i+1],p))
return false;
}
return true;
}
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
cin >> polySize;
for (int i = 0; i < polySize; ++i) {
cin >> polygon[i];
}
polygon[polySize] = polygon[0];
cin >> numPoint;
while (numPoint--) {
Point p; cin >> p;
cout << (inPolygon(p) ? "YES\n" : "NO\n");
}
return 0;
}
Chặt nhị phân - \(O(log(N))\)
#include <bits/stdc++.h>
#define Point Vector
using namespace std;
struct Vector {
int x, y;
Vector() { x = y = 0; }
Vector(int xx, int yy) {
x = xx; y = yy;
}
Vector operator - (const Vector &v) const {
return Vector(x-v.x,y-v.y);
}
long long operator % (const Vector &v) const {
return 1LL * x * v.y - 1LL * y * v.x;
}
friend bool CCW(const Point &a, const Point &b, const Point &c) {
return (b-a) % (c-b) > 0;
}
friend istream& operator >> (istream&is, Vector &v) {
is >> v.x >> v.y;
return is;
}
};
const int N = 5007;
int polySize, numPoint;
Point polygon[N];
int binarySearch(const Point &p) {
int l = 0;
int r = polySize-1;
while (l < r) {
int m = l+r+1>>1;
if (CCW(polygon[0],polygon[m],p))
l = m;
else r = m-1;
}
return l;
}
bool inPolygon(const Point &p) {
if (!CCW(polygon[0],polygon[1],p)) return false;
if (!CCW(polygon[polySize-1],polygon[0],p)) return false;
int pos = binarySearch(p);
return CCW(polygon[pos],polygon[pos+1],p);
}
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
cin >> polySize;
for (int i = 0; i < polySize; ++i) {
cin >> polygon[i];
}
cin >> numPoint;
while (numPoint--) {
Point p; cin >> p;
cout << (inPolygon(p) ? "YES\n" : "NO\n");
}
return 0;
}
Trường hợp kiểm tra trong đa giác tổng quát
Đề bài: https://cses.fi/problemset/task/2192/
Độ phức tạp: \(O(N)\)
#include <bits/stdc++.h>
#define Point Vector
using namespace std;
const double PI = acos(-1);
const double EPS = 1e-9;
struct Vector {
int x, y;
Vector() { x = y = 0; }
Vector(int xx, int yy) {
x = xx; y = yy;
}
Vector operator - (const Vector &v) const {
return Vector(x-v.x,y-v.y);
}
long long operator % (const Vector &v) const {
return 1LL * x * v.y - 1LL * y * v.x;
}
long long operator * (const Vector &v) const {
return 1LL * x * v.x + 1LL * y * v.y;
}
friend bool collinear(const Point &a, const Point &b, const Point &c) {
return (b-a) % (c-b) == 0;
}
friend double angle(const Vector &a, const Vector &b) {
return atan2(a%b,a*b);
}
friend istream& operator >> (istream&is, Vector &v) {
is >> v.x >> v.y;
return is;
}
};
const int N = 5007;
int polySize, numPoint;
Point polygon[N];
bool isBoundary(const Point &p) {
for (int i = 0; i < polySize; ++i) {
if (collinear(polygon[i],polygon[i+1],p)) {
if ((polygon[i]-p) * (polygon[i+1]-p) <= 0)
return true;
}
}
return false;
}
bool isInside(const Point &p) { // not isBoundary
double sum = 0;
for (int i = 0; i < polySize; ++i) {
sum += angle(polygon[i]-p,polygon[i+1]-p);
}
return fabs(fabs(sum) - PI*2) < EPS;
}
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
cin >> polySize >> numPoint;
for (int i = 0; i < polySize; ++i) {
cin >> polygon[i];
}
polygon[polySize] = polygon[0];
while (numPoint--) {
Point p; cin >> p;
if (isBoundary(p)) {
cout << "BOUNDARY\n";
}
else if (isInside(p)) {
cout << "INSIDE\n";
}
else {
cout << "OUTSIDE\n";
}
}
return 0;
}