zoukankan      html  css  js  c++  java
  • hdu 2823 The widest road (Convex Hull)

    http://acm.hdu.edu.cn/showproblem.php?pid=2823

      应该是经典的凸包间最短距离的题目吧。印象中是用旋转卡壳来过的,不过我在hdu水了一下,一个暴力O(n^2)算法直接撸过。

      我的做法很简单,就是先判断两个凸包是否相交或包含,然后就用点到线段距离枚举凸包间距离,加了一个遇到距离增加的时候剪枝就过了。

    代码如下:

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <cmath>
      4 #include <vector>
      5 #include <algorithm>
      6 #include <iostream>
      7 
      8 using namespace std;
      9 
     10 struct Point {
     11     double x, y;
     12     Point() { x = y = 0.0;}
     13     Point(double x, double y) : x(x), y(y) {}
     14 } ;
     15 template <class T> T sqr(T x) { return x * x;}
     16 inline double ptDis(Point a, Point b) { return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y));}
     17 
     18 typedef Point Vec;
     19 Vec operator + (Vec a, Vec b) { return Vec(a.x + b.x, a.y + b.y);}
     20 Vec operator - (Vec a, Vec b) { return Vec(a.x - b.x, a.y - b.y);}
     21 Vec operator * (Vec a, double p) { return Vec(a.x * p, a.y * p);}
     22 Vec operator / (Vec a, double p) { return Vec(a.x / p, a.y / p);}
     23 
     24 const double EPS = 1e-8;
     25 const double PI = acos(-1.0);
     26 inline int sgn(double x) { return fabs(x) < EPS ? 0 : (x < 0 ? -1 : 1);}
     27 bool operator < (Point a, Point b) { return a.x < b.x || a.x == b.x && a.y < b.y;}
     28 bool operator == (Point a, Point b) { return !sgn(a.x - b.x) && !sgn(a.y - b.y);}
     29 
     30 inline double dotDet(Vec a, Vec b) { return a.x * b.x + a.y * b.y;}
     31 inline double crossDet(Vec a, Vec b) { return a.x * b.y - a.y * b.x;}
     32 inline double crossDet(Point o, Point a, Point b) { return crossDet(a - o, b - o);}
     33 inline double vecLen(Vec x) { return sqrt(dotDet(x, x));}
     34 
     35 struct Line {
     36     Point s, t;
     37     Line() {}
     38     Line(Point s, Point t) : s(s), t(t) {}
     39 } ;
     40 
     41 inline int onSeg(Point x, Point a, Point b) { return sgn(crossDet(x, a, b)) == 0 && sgn(dotDet(a - x, b - x)) < 0;}
     42 
     43 int segIntersect(Point a, Point c, Point b, Point d) {
     44     Vec v1 = b - a, v2 = c - b, v3 = d - c, v4 = a - d;
     45     int a_bc = sgn(crossDet(v1, v2));
     46     int b_cd = sgn(crossDet(v2, v3));
     47     int c_da = sgn(crossDet(v3, v4));
     48     int d_ab = sgn(crossDet(v4, v1));
     49     if (a_bc * c_da > 0 && b_cd * d_ab > 0) return 1;
     50     if (onSeg(b, a, c) && c_da) return 2;
     51     if (onSeg(c, b, d) && d_ab) return 2;
     52     if (onSeg(d, c, a) && a_bc) return 2;
     53     if (onSeg(a, d, b) && b_cd) return 2;
     54     return 0;
     55 }
     56 
     57 int andrew(Point *pt, int n, Point *ch) {
     58 //    cout << "sort!!" << n << endl;
     59     sort(pt, pt + n);
     60     int m = 0;
     61 //    cout << "here??" << endl;
     62     for (int i = 0; i < n; i++) {
     63         while (m > 1 && crossDet(ch[m - 2], ch[m - 1], pt[i]) <= 0) m--;
     64         ch[m++] = pt[i];
     65     }
     66     int k = m;
     67     for (int i = n - 2; i >= 0; i--) {
     68         while (m > k && crossDet(ch[m - 2], ch[m - 1], pt[i]) <= 0) m--;
     69         ch[m++] = pt[i];
     70     }
     71     if (n > 1) m--;
     72     return m;
     73 }
     74 
     75 int ptInPoly(Point p, Point *poly, int n) {
     76     int wn = 0;
     77     poly[n] = poly[0];
     78     for (int i = 0; i < n; i++) {
     79         if (onSeg(p, poly[i], poly[i + 1])) return -1;
     80         int k = sgn(crossDet(poly[i], poly[i + 1], p));
     81         int d1 = sgn(poly[i].y - p.y);
     82         int d2 = sgn(poly[i + 1].y - p.y);
     83         if (k > 0 && d1 <= 0 && d2 > 0) wn++;
     84         if (k < 0 && d2 <= 0 && d1 > 0) wn--;
     85     }
     86     if (wn != 0) return 1;
     87     return 0;
     88 }
     89 
     90 const int N = 1111;
     91 Point pt[2][N], ch[2][N];
     92 
     93 bool polyApart(Point *a, int n, Point *b, int m) {
     94     a[n] = a[0], b[m] = b[0];
     95     for (int i = 0; i < n; i++) if (ptInPoly(a[i], b, m)) return false;
     96     for (int i = 0; i < m; i++) if (ptInPoly(b[i], a, n)) return false;
     97     for (int i = 0; i < n; i++) {
     98         for (int j = 0; j < m; j++) {
     99             if (segIntersect(a[i], a[i + 1], b[j], b[j + 1])) return false;
    100         }
    101     }
    102     return true;
    103 }
    104 
    105 double pt2Line(Point x, Point a, Point b) {
    106     Vec v1 = b - a, v2 = x - a;
    107     return crossDet(v1, v2) / vecLen(v1);
    108 }
    109 
    110 double pt2Seg(Point x, Point a, Point b) {
    111     if (a == b) return vecLen(x - a);
    112     Vec v1 = b - a, v2 = x - a, v3 = x - b;
    113     if (sgn(dotDet(v1, v2)) < 0) return vecLen(v2);
    114     if (sgn(dotDet(v1, v3)) > 0) return vecLen(v3);
    115     return fabs(crossDet(v1, v2)) / vecLen(v1);
    116 }
    117 
    118 const double FINF = 1e100;
    119 
    120 double polyDis(Point *a, int n, Point *b, int m) {
    121     if (!polyApart(a, n, b, m)) return 0.0;
    122     a[n] = a[0], b[m] = b[0];
    123     double mini = FINF;
    124     for (int i = 0; i < n; i++) {
    125         double last, cur;
    126         for (int j = 0; j < m; j++) {
    127             cur = pt2Seg(b[j], a[i], a[i + 1]);
    128             mini = min(mini, cur);
    129             if (j && last < cur) break;
    130             last = cur;
    131         }
    132     }
    133     for (int i = 0; i < m; i++) {
    134         double last, cur;
    135         for (int j = 0; j < n; j++) {
    136             cur = pt2Seg(a[j], b[i], b[i + 1]);
    137             mini = min(mini, cur);
    138             if (j && last < cur) break;
    139             last = cur;
    140         }
    141     }
    142     return mini;
    143 }
    144 
    145 int main() {
    146 //    freopen("in", "r", stdin);
    147     int n[2];
    148     while (~scanf("%d%d", &n[0], &n[1])) {
    149         for (int i = 0; i < 2; i++) {
    150             for (int j = 0; j < n[i]; j++) {
    151                 scanf("%lf%lf", &pt[i][j].x, &pt[i][j].y);
    152             }
    153             n[i] = andrew(pt[i], n[i], ch[i]);
    154         }
    155         printf("%.4f\n", polyDis(ch[0], n[0], ch[1], n[1]));
    156     }
    157     return 0;
    158 }
    View Code

    ——written by Lyon

  • 相关阅读:
    PHP中get请求中参数的key不能是para
    js对数组中的数字排序
    js 数组不重复添加元素
    Controllers
    Views
    Models
    Requirements
    Pull Requests
    Upgrade Guide
    Overview & Change Log
  • 原文地址:https://www.cnblogs.com/LyonLys/p/hdu_2823_Lyon.html
Copyright © 2011-2022 走看看