poj1912(*判斷直線是否穿過凸多邊形)

/*
translation:
	給定一些點,再給出若干條直線,對於每一條直線,判斷其所有點是否都在同一側
solution:
	很容易想到先求凸包,然後再對凸包上面的點做處理。
note:
	* 很明顯,只要直線不經過凸包即可。但是怎麼快速判斷就成了問題。方法是根據凸包上面的點進行二分查找第一個在右側或者左側的點。
	  因爲凸包上的點的斜率呈現單調性,故可行。然後對兩個點判斷是否都在直線同一側。
*/
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cmath>
#include <algorithm>

using namespace std;
const int maxn = 100000 + 5;
const double INF = 0x3f3f3f3f * 1.0;
const double M_PI = 3.14159265358979323846;

struct Point
{
    double x, y;
    Point(){}
    Point(double x_, double y_):x(x_),y(y_){}
} p[maxn], q[maxn], dup[maxn], convex[maxn];
typedef Point Vector;
int n;

Vector operator + (Vector a, Vector b)  { return Vector(a.x + b.x, a.y + b.y); }
Vector operator - (Point a, Point b)    { return Point(a.x - b.x, a.y - b.y); }
Vector operator * (Vector a, double p)  { return Vector(a.x * p, a.y * p); }
Vector operator / (Vector a, double p)  { return Vector(a.x / p, a.y / p); }

bool operator < (const Point& a, const Point& b)
{
    return a.x < b.x || (a.x == b.x && a.y < b.y);
}

const double eps = 1e-10;
int dcmp(double x)
{
    if(fabs(x) < eps)    return 0;
    else                return x < 0 ? -1 : 1;
}

bool operator == (const Point& a, const Point& b)
{
    return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
}

double dot(Vector a, Vector b)      { return a.x * b.x + a.y * b.y; }
double length(Vector a)             { return sqrt(dot(a, a)); }
double angle(Vector a, Vector b)    { return acos(dot(a, b) / length(a) / length(b)); }
double angle(Vector v)              { return atan2(v.y, v.x); }
double cross(Vector a, Vector b)    { return a.x * b.y - b.x * a.y; }
double dist(Point p1,Point p2)      { return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)); }
double area(Point a, Point b, Point c) { return cross(b - a, c - a); }

int convexHull(Point* p, int n, Point* ch)
{
    sort(p, p + n);
    int m = 0;
    for(int i = 0; i < n; i++) {
        while(m > 1 && cross(ch[m-1] - ch[m-2], p[i] - ch[m-2]) <= 0) m--;
        ch[m++] = p[i];
    }
    int k = m;
    for(int i = n-2; i >= 0; i--) {
        while(m > k && cross(ch[m-1] - ch[m-2], p[i] - ch[m-2]) <= 0) m--;
        ch[m++] = p[i];
    }
    if(n > 1) m--;
    return m;
}

double ang[maxn];
bool dcmp2(double lhs, double rhs)
{
	return lhs + eps < rhs;
}

inline double normalize(double r)
{
	if (r < -M_PI / 2.0 + eps) r += M_PI * 2;
	return r;
}

inline double atan2(const Point& p)
{
	return normalize(atan2(p.y, p.x));
}

int main()
{
	//freopen("in.txt", "r", stdin);
    scanf("%d", &n);
    for(int i = 0; i < n; i++)	scanf("%lf%lf", &p[i].x, &p[i].y);

    int m;
    if(n > 1) m = convexHull(p, n, convex);
    else	  m = 1;

    convex[m] = convex[0];
    for(int i = 0; i < m; i++) {
		ang[i] = atan2(convex[i+1] - convex[i]);
    }

	sort(ang, ang + m, dcmp2);
    Point a, b;
    while(~scanf("%lf%lf%lf%lf", &a.x, &a.y, &b.x, &b.y)) {
		if(n == 1) {
			printf("GOOD\n");
			continue;
		}

		int i = upper_bound(ang, ang + m, atan2(a - b), dcmp2) - ang;
		int j = upper_bound(ang, ang + m, atan2(b - a), dcmp2) - ang;

		if(cross(b - a, convex[i] - a) * cross(b - a, convex[j] - a) > -eps)
			printf("GOOD\n");
		else
			printf("BAD\n");
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章