• POJ 1584 计算几何 凸包


    链接:

    http://poj.org/problem?id=1584

    题意:

    按照顺时针或逆时针方向输入一个n边形的顶点坐标集,先判断这个n边形是否为凸包。

    再给定一个圆形(圆心坐标和半径),判断这个圆是否完全在n变形内部。

    题解:

    1、判断凸包convex():

       由于点集已经按某个时针方向有序,因此可以先定义一个方向系数dir=0

       两两枚举n边形的边,用叉积判断这两条边的转向(右螺旋或左螺旋),由于存在散点共线的情况,因此当且仅当叉积的值t第一次不为0时,dir=t,dir的值此后不再改变。(dir>0 则为右螺旋逆时针,dir<0则为左螺旋顺时针)

       此后继续枚举剩下的边,只要判断dir*t>=0即可,当存在一个dir*t<0的边,说明这是凹多边形,就不是凸包了。

    2、判断圆心在不在凸包内contain()

    3、当圆心在凸包内时,判断距离是否都大于半径fit()

    代码:

      1 #include <map>
      2 #include <set>
      3 #include <cmath>
      4 #include <queue>
      5 #include <stack>
      6 #include <cstdio>
      7 #include <string>
      8 #include <vector>
      9 #include <cstdlib>
     10 #include <cstring>
     11 #include <sstream>
     12 #include <iostream>
     13 #include <algorithm>
     14 #include <functional>
     15 using namespace std;
     16 #define rep(i,a,n) for (int i=a;i<n;i++)
     17 #define per(i,a,n) for (int i=n-1;i>=a;i--)
     18 #define all(x) (x).begin(),(x).end()
     19 #define pb push_back
     20 #define mp make_pair
     21 #define lson l,m,rt<<1  
     22 #define rson m+1,r,rt<<1|1 
     23 typedef long long ll;
     24 typedef vector<int> VI;
     25 typedef pair<int, int> PII;
     26 const ll MOD = 1e9 + 7;
     27 const int INF = 0x3f3f3f3f;
     28 const int MAXN = 1010;
     29 // head
     30 
     31 const double eps = 1e-8;
     32 int cmp(double x) {
     33     if (fabs(x) < eps) return 0;
     34     if (x > 0) return 1;
     35     return -1;
     36 }
     37 
     38 const double pi = acos(-1);
     39 inline double sqr(double x) {
     40     return x*x;
     41 }
     42 struct point {
     43     double x, y;
     44     point() {}
     45     point(double a, double b) :x(a), y(b) {}
     46     void input() {
     47         scanf("%lf%lf", &x, &y);
     48     }
     49     friend point operator+(const point &a, const point &b) {
     50         return point(a.x + b.x, a.y + b.y);
     51     }
     52     friend point operator-(const point &a, const point &b) {
     53         return point(a.x - b.x, a.y - b.y);
     54     }
     55     friend point operator*(const double &a, const point &b) {
     56         return point(a*b.x, a*b.y);
     57     }
     58     friend point operator/(const point &a, const double &b) {
     59         return point(a.x / b, a.y / b);
     60     }
     61     double norm() {
     62         return sqrt(sqr(x) + sqr(y));
     63     }
     64 };
     65 double det(point a, point b) {
     66     return a.x*b.y - a.y*b.x;
     67 }
     68 double dot(point a, point b) {
     69     return a.x*b.x + a.y*b.y;
     70 }
     71 double dist(point a, point b) {
     72     return (a - b).norm();
     73 }
     74 
     75 struct line {
     76     point a, b;
     77     line() {}
     78     line(point x, point y) :a(x), b(y) {}
     79 };
     80 double dis_point_segment(point p, point s, point t) {
     81     if (cmp(dot(p - s, t - s)) < 0) return (p - s).norm();
     82     if (cmp(dot(p - t, s - t)) < 0) return (p - t).norm();
     83     return fabs(det(s - p, t - p) / dist(s, t));
     84 }
     85 bool point_on_segment(point p, point s, point t) {
     86     return cmp(det(p - s, t - s)) == 0 && cmp(dot(p - s, p - t)) <= 0;
     87 }
     88 bool parallel(line a, line b) {
     89     return !cmp(det(a.a - a.b, b.a - b.b));
     90 }
     91 bool line_make_point(line a, line b,point &res) {
     92     if (parallel(a, b)) return false;
     93     double s1 = det(a.a - b.a, b.b - b.a);
     94     double s2 = det(a.b - b.a, b.b - b.a);
     95     res = (s1*a.b - s2*a.a) / (s1 - s2);
     96     return true;
     97 }
     98 
     99 int n;
    100 double r;
    101 point o;
    102 point *p;
    103 
    104 bool convex() {
    105     int dir = 0;
    106     rep(i, 0, n) {
    107         int t = cmp(det(p[i + 1] - p[i], p[i + 2] - p[i + 1]));
    108         if (!dir) dir = t;
    109         if (dir*t < 0) return false;
    110     }
    111     return true;
    112 }
    113 
    114 bool contain() {
    115     int sign = 0;
    116     rep(i, 0, n) {
    117         int x = cmp(det(p[i] - o, p[i + 1] - o));
    118         if (x) {
    119             if (sign && sign != x) return false;
    120             else sign = x;
    121         }
    122     }
    123     return true;
    124 }
    125 
    126 bool fit() {
    127     rep(i, 0, n) {
    128         int k = cmp(dis_point_segment(o, p[i], p[i + 1]) - r);
    129         if (k < 0) return false;
    130     }
    131     return true;
    132 }
    133 
    134 int main() {
    135     while (cin >> n && n != 1) {
    136         cin >> r;
    137         o.input();
    138         p = new point[n + 2];
    139         rep(i, 1, n + 1) p[i].input();
    140         p[0] = p[n];
    141         p[n + 1] = p[1];
    142         if(!convex()) cout << "HOLE IS ILL-FORMED" << endl;
    143         else {
    144             bool fg1 = contain();
    145             bool fg2 = fit();
    146             if (fg1 && fg2) cout << "PEG WILL FIT" << endl;
    147             else cout << "PEG WILL NOT FIT" << endl;
    148         }
    149         delete p;
    150     }
    151     return 0;
    152 }
  • 相关阅读:
    go包之logrus显示日志文件与行号
    linux几种快速清空文件内容的方法
    (转)CSS3之pointer-events(屏蔽鼠标事件)属性说明
    Linux下source命令详解
    控制台操作mysql常用命令
    解决beego中同时开启http和https时,https端口占用问题
    有关亚马逊云的使用链接收集
    favicon.ico--网站标题小图片二三事
    js获取url协议、url, 端口号等信息路由信息
    (转) Golang的单引号、双引号与反引号
  • 原文地址:https://www.cnblogs.com/baocong/p/6730953.html
Copyright © 2020-2023  润新知