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

转载于:https://www.cnblogs.com/LyonLys/archive/2013/05/27/hdu_2823_Lyon.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值