1. 程式人生 > >poj 1912 A highway and the seven dwarfs

poj 1912 A highway and the seven dwarfs

n) visit += clock build lan opera script following

A highway and the seven dwarfs
Time Limit: 8000MS Memory Limit: 30000K
Total Submissions: 2622 Accepted: 535
Case Time Limit: 3000MS

Description

Once upon a time, there was a land where several families of dwarfs were living. This land was called Dwarfland. Each family lived in one house. Dwarfs were often visiting their friends from the other families. Because the Dwarfland was free of evil, it happened that each dwarf visited each other during some short period of time.

Once, the humans living in countries around Dwarfland decided to build several straight highways. As the humans weren‘t aware of the dwarfs, some of the planned highways passed through Dwarfland. The dwarfs discovered this and were quite unhappy about it. The dwarfs are very little, and also very slow, so they are unable to cross the highway safely.

The dwarfs managed to get the plans for the highways somehow, and now they need your help. They would like to keep on visiting each other, so they don‘t like those highways which divide their houses into two non-empty parts. After they find out which highways they don‘t like, they will magically prevent the humans from building them.

The dwarfs are very little, and cannot reach the keyboard. So they asked for your help.

Task


Given is a number N of points (houses) in the plane and several straight lines (highways). For each given line, your task is to determine whether all N points lie on the same side of the line or not. Your program has to output the answer for the currently processed line before reading the description of the next one. You may assume that no highway passes through any of the houses.

Input

Your program is supposed to read the input from the standard input and write its output to the standard output. The first line of the input contains one integer N ( 0 < = N < = 100 000). N lines follow, the i-th of them contains two real numbers xi, yi ( -109 < = xi, yi < = 109) separated by a single space - the coordinates of the i-th house.

Each of the following lines contains four real numbers X1, Y1, X2, Y2 ( -109
< = X1, Y1, X2, Y2 < = 109) separated by a single space. These numbers are the coordinates of two different points [X1, Y1] and [X2, Y2], lying on the highway.

Output

For each line of input, your program is supposed to output a line containing the string "GOOD" if all of the given points are on the same side of the given line, or "BAD" if the given line divides the points.

Sample Input

4
0.0 0
6.00 -0.001
3.125 4.747
4.747 0.47
5 3 7 0
4 -4.7 7 4.7
4 47 4 94

Sample Output

GOOD
BAD
BAD

Hint

Huge input,scanf is recommended.
技術分享 題意:給定平面上幾個點的坐標,再給出一條直線,判斷這條直線是不是能把點分離成兩部分 思路:先找平面上這些點的凸包,那麽要是凸包和直線相交,則直線肯定可以把點分離成兩部分,問題的關鍵在於判斷直線是否和凸包相交。 可以將凸包的每條邊以及直線都考慮成向量的形式,那麽凸包的邊所形成的向量在極坐標系下的極角大小變化一定是單調的,可以看下圖: 技術分享      技術分享

第一幅圖中,向量AE,ED,DC,CB,BA的極角在 坐標系中變化是單調的,於是把他們都移到圖二中來,都以O點為起點,按照極角大小排序並編號,凸包的算法因人而異,我現在用的凸包算法是以最左端的A點開始存儲,並按照逆時針方向存儲點的,那麽AE向量最好標記為極角最小的向量,ED次之,以此類推,那麽我們就得設定極角的變化範圍為(-90,270],這樣將所有的向量排好序,並標記好編號,譬如右圖的1向量代表AE向量。。。現在又給出一條直線L1,如何得知L1和凸包相交呢?我們平移L1的向量形式,移到L1只割掉了凸包一個點的位置(一共兩個位置),L2的方向為p1p2,L3的方向為p2p1,我們發現這兩條向量如果都要逆時針轉一個方向,分別轉動到向量DC和向量BA的位置需要轉動的角度是最小的,而向量DC和BA的端點D,B又恰恰是向量L3和L1所割掉的點那麽如果線段DB和直線L1有交點,則L1一定和凸包存在交點的。這個規律放到圖二來看,直線L的向量形式為p2p1,轉到向量3是所轉角度最小的,其反向的向量轉到向量5轉角度又是最小的,向量3與向量5都是可以通過二分查找找出來,找到向量之後在取其起始端點,判斷這兩個起始端點是否與直線相交。

AC代碼:

#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<set>
#include<vector>
#include<cstring>
#include<string>
#include<functional>
#include<cmath>
#include<stack>
using namespace std;
const int N_MAX = 100000 + 5;
#define INF 0x3f3f3f3f
#define EPS 1e-10
#define equals(a,b) (fabs(a-b)<EPS)
#define pi acos(-1.0)
#define BOTTOM 0
#define LEFT 1
#define RIGHT 2
#define TOP 3

static const int COUNTER_CLOCKWISE = -1;
static const int CLOCKWISE = 1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

double add(double a,double b) {
    if (abs(a + b) < EPS*(abs(a) + abs(b)))return 0;
    return a + b;
}

class point {
public:
    double x, y;
    point(double x = 0, double y = 0) :x(x), y(y) {}
    point operator +(point p) { return point(x+p.x, y+p.y); }
    point operator -(point p) { return point(x - p.x,y - p.y); }
    point operator *(double a) { return point(a*x, a*y); }
    point operator /(double a) { return point(x / a, y / a); }
    double norm() { return x*x + y*y; }
    double abs() { return sqrt(norm()); }
    bool operator<(const point&p)const {
        return x != p.x ? x < p.x : y < p.y;
    }
    bool operator ==(const point&p)const {
        return x == p.x && y == p.y;
    }
    double dot(point p) {
        return x*p.x+y*p.y;
    }
    double det(point p) {
        return x*p.y- y*p.x;
    }
};

struct Segment {
    point p1, p2;
    Segment(point p1 = point(), point p2 = point()) :p1(p1), p2(p2) {}
};
typedef Segment line;

typedef vector<point>Polygon;
//????????????p0p1?????????p0p2???????????????
int ccw(point p0, point p1, point p2) {
    point a = p1 - p0;
    point b = p2 - p0;
    if (a.det(b) > EPS)return COUNTER_CLOCKWISE;
    if (a.det(b) < -EPS)return CLOCKWISE;
    if (a.dot(b) < -EPS)return ONLINE_BACK;
    if (a.norm() >= b.norm())return ON_SEGMENT;//!!
    return ONLINE_FRONT;
}
//????????????p1p2???p3p4????????????
bool intersect(point p1, point p2, point p3, point p4) {
    return (ccw(p1, p2, p3)*ccw(p1, p2, p4) < 0 &&
        ccw(p3, p4, p1)*ccw(p3, p4, p2) < 0);//!!!!!!!!!!!!!!!!!!!!!!!!!!!
}


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

double arg(const point& p) { return normalize(atan2(p.y, p.x)); }
inline bool double_cmp(double a,double b) {
    return a + EPS < b;
}


////
typedef vector<point>Polygon;



vector<point> convex_hull(point *ps, int N)
{
    sort(ps, ps + N);
    int k = 0;   // 凸包的頂點數
    vector<point> qs(N * 2);   // 構造中的凸包
                           // 構造凸包的下側
    for (int i = 0; i < N; ++i)
    {
        while (k > 1 && (qs[k - 1] - qs[k - 2]).det(ps[i] - qs[k - 1]) <= 0) --k;
        qs[k++] = ps[i];
    }
    // 構造凸包的上側
    for (int i = N - 2, t = k; i >= 0; --i)
    {
        while (k > t && (qs[k - 1] - qs[k - 2]).det(ps[i] - qs[k - 1]) <= 0) --k;
        qs[k++] = ps[i];
    }
    qs.resize(k - 1);
    return qs;
}

point s[N_MAX];
int n;
double a[N_MAX];//記錄凸包每條邊行成的向量傾斜度
int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        scanf("%lf%lf", &s[i].x, &s[i].y);  
    }
    int N;
    Polygon con;
    if (n > 1) { 
        
         con=convex_hull(s,n);
        N = con.size();
        con.push_back(con[0]);
    }
        for (int i = 0; i <N; i++) {
            a[i] = arg(con[i + 1] - con[i]);
        }
    
    sort(a, a + N, double_cmp);
    point p1, p2;
    while (scanf("%lf%lf%lf%lf",&p1.x,&p1.y,&p2.x,&p2.y)!=EOF) {
        if (n < 2) { puts("GOOD"); continue; }
        int i = upper_bound(a, a + N, arg(p2 - p1), double_cmp) - a;
        int j = upper_bound(a, a + N, arg(p1 - p2), double_cmp) - a;
        puts((((p2 - p1).det(con[i] - p1) * (p2 - p1).det(con[j] - p1) > -EPS)) ? "GOOD" : "BAD");
    
    }

    return 0;
}

poj 1912 A highway and the seven dwarfs