uva 361 - Cops and Robbers(凸包)

来源:互联网 发布:矩阵奇异值分解 matlab 编辑:程序博客网 时间:2024/04/30 01:51

题目中给出了n个cops和m个robbers和q个居民,如果一个居民在某三个cops围成的三角形中就是安全的,否则,如果在某三个robbers围成的三角形中,就是不安全的,不然就是neither。


思路:这个可以转换成凸包来做。判断某个居民是不是在某个凸包内部就行了。
:下面是凸包的求法之一

/*****************************************Author      :Crazy_AC(JamesQi)Time        :2016File Name   :*****************************************/// #pragma comment(linker, "/STACK:1024000000,1024000000")#include <iostream>#include <algorithm>#include <iomanip>#include <sstream>#include <string>#include <stack>#include <queue>#include <deque>#include <vector>#include <map>#include <set>#include <cstdio>#include <cstring>#include <cmath>#include <cstdlib>#include <climits>using namespace std;#define MEM(x,y) memset(x, y,sizeof x)#define pk push_back#define lson rt << 1#define rson rt << 1 | 1#define bug cout << "BUG HERE\n"typedef long long LL;typedef unsigned long long ULL;typedef pair<int,int> ii;typedef pair<ii,int> iii;const double eps = 1e-8;const double pi = 4 * atan(1);const int inf = 1 << 30;const int INF = 0x3f3f3f3f;const int MOD = 1e9 + 7;int nCase = 0;int dcmp(double x){//精度正负、0的判断    if (fabs(x) < eps) return 0;    return x < 0?-1:1;}inline int read(){    char c = getchar();    while (!isdigit(c)) c = getchar();    int x = 0;    while (isdigit(c)) {        x = x * 10 + c - '0';        c = getchar();    }    return x;}const int maxn = 321;struct point {    double x, y;    void read() {        scanf("%lf %lf", &x, &y);    }    point() {}    point(double x,double y) {        this->x = x;        this->y = y;    }    bool operator == (const point& rhs) const {        return dcmp(x - rhs.x) == 0 && dcmp(y - rhs.y) == 0;    }    bool operator < (const point& rhs) const {        return x < rhs.x || (x == rhs.x && y < rhs.y);    }    point operator - (const point& rhs) {        return point(x - rhs.x, y - rhs.y);    }    double operator * (const point& rhs) {        return x * rhs.y - y * rhs.x;    }}p[maxn], a[maxn], b[maxn], A[maxn], B[maxn];int n, m, q;int numa, numb;double Cross(point a1, point b1) {    return a1.x * b1.y - a1.y * b1.x;}double Dot(point a1, point b1) {    return a1.x * b1.x + a1.y * b1.y;}int getConvexHull(point* o, int num, point* buff) {    sort(o, o + num);    int top = 0;    for (int i = 0;i < num;++i) {        while(top > 1 && dcmp(Cross(buff[top - 1] - buff[top - 2], o[i] - buff[top - 1])) <= 0)            top--;        buff[top++] = o[i];    }    int k = top;    for (int i = num - 2;i >= 0;--i) {        while(top > k && dcmp(Cross(buff[top - 1] - buff[top - 2], o[i] - buff[top - 2])) <= 0)            top--;        buff[top++] = o[i];    }    if (num > 1) top--;    return top;}//点在险段上,不包含端点bool onSegment(point o, point a1, point b1) {    return dcmp(Cross(a1 - o, b1 - o)) == 0 && dcmp(Dot(a1 - o, b1 - o)) < 0;}//点在凸多边形内int InPolygnal(point o, point* buff, int num) {    for (int i = 0;i < num;++i) if (o == buff[i]) return 0;//点重合    if (num >= 2) {        for (int i = 0;i < num;++i) {            int v = (i + 1) % num;            if (onSegment(o, buff[i], buff[v])) return 0;//在线段上        }    }    if (num <= 2) return 1;    int sig = dcmp(Cross(o - buff[0] , buff[1] - buff[0]));//这个地方,因为做了个凸包,所以是逆时针排好序的。    for (int i = 0;i < num;++i) {        int v = (i + 1) % num;        int tsig = dcmp(Cross(o - buff[i] , buff[v] - buff[i]));        if (sig != tsig) return 1;//在外部    }    return -1;//在内部}void input() {    for (int i = 0;i < n;++i)         A[i].read();    for (int i = 0;i < m;++i)         B[i].read();    sort(A, A + n);    sort(B, B + m);    numa = unique(A, A + n) - A;    numb = unique(B, B + m) - B;    numa = getConvexHull(A, numa, a);    numb = getConvexHull(B, numb, b);}int main(int argc, const char * argv[]){       // freopen("in.txt","r",stdin);    // freopen("out.txt","w",stdout);    while(cin >> n >> m >> q && n + m + q) {        input();        printf("Data set %d:\n", ++nCase);        int x, y;        for (int i = 0;i < q;++i) {            scanf("%d %d", &x, &y);            if (n > 2 && InPolygnal(point(x, y), a, numa) <= 0) {                printf("     Citizen at (%d,%d) is safe.\n", x, y);            }else if (m > 2 && InPolygnal(point(x, y), b, numb) <= 0) {                printf("     Citizen at (%d,%d) is robbed.\n", x, y);            }else {                printf("     Citizen at (%d,%d) is neither.\n", x, y);            }        }        puts("");    }    return 0;}
0 0
原创粉丝点击