POJ 1584 计算几何基础判断

这个题目就是让你判断三件事情
1. 这些点能不能构成一个凸包
2. 圆心是不是在这个凸包的内部
3. 这个凸包能不能包含这个圆
第一个根据凸包的性质用叉积判断一下下就好了
第二个的话根据多边形的一个性质 在内部的点的 与所有点连接起来所有的角加起来是 360 度
第三个的话通过距离判断一下就可以了“`

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>

using namespace std;
const int maxn = 5005;
const double eps = 1e-4;
const double PI = 3.1415926;
struct point {
    double x,y;
}p[maxn];
struct circle {
    point p;
    double r;
}C;
int n;

double ab (double x) {
    return x > 0 ? x : -x;
}

int sgn (double x) {
    if (ab (x) <= eps) return 0;
    return x > 0 ? 1 : -1;
}
double cross (double x1,double y1,double x2,double y2) {
    return x1 * y2 - x2 * y1;
}

double xmult (double x1,double y1,double x2,double y2) {
    return x1 * x2 + y1 * y2;
}

double dist (point a,point b) {
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}

bool is_tu () {
    p[n + 1] = p[1];
    int mark = 0;
    int i;
    for (i = 2;i <= n; ++ i) {
        point p1,p2,p3;
        p1 = p[i];
        p2 = p[i - 1];
        p3 = p[i + 1];
        mark = sgn (cross (p1.x - p2.x,p1.y - p2.y,p3.x - p1.x,p3.y - p1.y));
        if (mark) break;
    }
    for (;i <= n; ++ i) {
        point p1,p2,p3;
        p1 = p[i];
        p2 = p[i - 1];
        p3 = p[i + 1];
        if (sgn (cross (p1.x - p2.x,p1.y - p2.y,p3.x - p1.x,p3.y - p1.y)) != mark &&  sgn (cross (p1.x - p2.x,p1.y - p2.y,p3.x - p1.x,p3.y - p1.y))) return false;
    }
    return true;
}

double dis (point a,point b,point c) {
    if (xmult(b.x - a.x, b.y - a.y, c.x - a.x, c.y - a.y) <= 0) return dist (a,c);
    if (xmult(a.x - b.x, a.y - b.y, c.x - b.x, c.y - b.y) <= 0) return dist (b,c);
    double s = cross(a.x - c.x, a.y - c.y, b.x - c.x,b.y - c.y);
    double d = dist(a, b);
    return ab (s) / d;
}

bool in_poly () {
    double ang = 0;
    p[n + 1] = p[1];
    for (int i = 1;i <= n; ++ i) {
        point p1,p2,p3;
        p1 = p[i];
        p2 = p[i + 1];
        double a = dist (C.p,p1);
        double b = dist (C.p,p2);
        double c = dist (p1,p2);
        double value = (a*a + b*b - c*c) / (2 * a * b);
        ang += acos (value);
    }
    if (sgn(ab (ang - 2 * PI)) == 0) return true;
    return false;
}

bool is_ok () {
    p[n + 1] = p[1];
    for (int i = 1;i <= n; ++ i) {
        point p1,p2;
        p1 = p[i];
        p2 = p[i + 1];
        if (sgn (dis (p1,p2,C.p) - C.r) < 0) return false;
    }
    return true;
}

int main () {
    while (scanf ("%d",&n) != EOF) {
        if (n < 3) break;
        scanf ("%lf%lf%lf",&C.r,&C.p.x,&C.p.y);
        for (int i = 1;i <= n; ++ i) {
            scanf ("%lf%lf",&p[i].x,&p[i].y);
        }
        if (!is_tu()) {
            printf ("HOLE IS ILL-FORMED\n");
        }
        else if (!in_poly() || !is_ok()) {
            printf ("PEG WILL NOT FIT\n");
        }
        else {
            printf ("PEG WILL FIT\n");
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值