Poj 3608 bridge sans SS islands (returns the shortest distance between non-Intersecting convex hull)

Source: Internet
Author: User

Question link: http://poj.org/problem? Id = 3608

It indicates that the algorithm of rotating the card shell seems to be easy to understand (although it proved to be a little difficult, but it is better to understand it only), but the code implementation is still not very easy to understand.

The key lies in the calculation of ry. angle calculation is not involved as much as possible. It is basically a point area and a difference product, because this can avoid calling the system's trigonometric function, so it can minimize the accuracy.

Loss

The enumeration method can be used for this question, and the monotonicity of the convex hull can be used for pruning, but it is still easy to time out.

However, the complexity of the O (n) algorithm is the optimal algorithm in the sense of progressive time complexity.

First, select the lowest point of P and the highest point of Q. After completion, the shell is started and the area is used when the shell is stuck.

        while((rec=cross(q[pos_q],p[pos_p+1],p[pos_p])-cross(q[pos_q+1],p[pos_p+1],p[pos_p])) > eps)        {          pos_q=(pos_q+1)%m;        }        if(rec < -eps)        ans=MIN(ans,point_to_seg(p[pos_p],p[pos_p+1],q[pos_q]));        else        ans=MIN(ans,seg_to_seg(p[pos_p],p[pos_p+1],q[pos_q],q[pos_q+1]));        pos_p=(pos_p+1)%n;

If this time the area is larger than the next time, it means that the next step may be smaller, that is, the nearest point has not been found, and then down

However, there is another condition, that is, if the difference between the two areas is close to 0, it means that the two areas have not changed, and this is the shortest.

The distance is the shortest distance between the ANS and the two line segments. If the difference is not 0, It is the distance between the point and the line segment.

This is quite understandable, and then P starts at the next point after it is completed. Some people may think this algorithm is a square

The algorithm is actually linear, because the loop in it is only possible to turn half a circle at the first time, and then it is almost a constant!

Why do we need to enumerate the final results on both sides? One gets the lowest point, the other gets the highest point, and then the other way around!

The rotating card Shell Algorithm has not been fully understood yet, so you have to study it well!

# Include <iostream> # include <stdio. h> # include <string. h >#include <cmath> # include <algorithm> using namespace STD; # define INF 1e8 # define EPS 1e-8 # define max (A, B) (A> B? A: B) # define min (a, B) (a <B? A: B) struct point {Double X; Double Y;} p [11000], Q [11000]; struct line {point A; point B ;}; double Cross (point & A, point & B, point & C) {return (B. x-a.x) * (C. y-a.y)-(B. y-a.y) * (C. x-a.x);} double DIS (point & A, point & B) {return (. x-b.x) * (. x-b.x) +. y-b.y) * (. y-b.y);} int cmp_p (const void * a, const void * B) {return cross (P [0], * (point *) A, * (point *) b)> 0? -1: 1;} int cmp_q (const void * a, const void * B) {return cross (Q [0], * (point *) A, * (point *) b)> 0? -1: 1;} double dot (point a, point B) {return. x * B. X +. y * B. y;} double point_to_seg (point a, point B, point C) // The distance from A to B in a straight line {point AB, AC; AB. X = B. x-a.x; AB. y = B. y-a.y; AC. X = C. x-a.x; AC. y = C. y-a.y; double F = dot (AB, AC); If (F <0) return DIS (a, c); double F1 = dot (AB, AB ); if (F> F1) return DIS (B, c); F = f/F1; point D; D. X =. X + AB. x * F; D. y =. Y + AB. y * F; return DIS (D, C);} double seg_to_seg (Point A1, point B1, point A2, point B2) {Return min (point_to_seg (A1, B1, A2), point_to_seg (A1, B1, B2), min (point_to_seg (A2, B2, A1 ), point_to_seg (A2, B2, B1);} int n, m; double find_ans (point * P, int N, point * q, int m) {int I, j, k, pos_p, pos_q; double ans = inf, REC; P [N] = P [0]; Q [m] = Q [0]; pos_p = pos_q = 0; for (I = 1; I <n; I ++) if (P [I]. Y <p [pos_p]. y) pos_p = I; for (I = 1; I <m; I ++) if (Q [I]. y> q [pos_q]. y) pos_q = I; for (I = 0; I <n; I ++) {While (Rec = cross (Q [pos_q], p [Pos_p + 1], p [pos_p])-cross (Q [pos_q + 1], p [pos_p + 1], p [pos_p])> EPS) {pos_q = (pos_q + 1) % m;} If (REC <-EPS) ans = min (ANS, point_to_seg (P [pos_p], p [pos_p + 1], Q [pos_q]); else ans = min (ANS, seg_to_seg (P [pos_p], p [pos_p + 1], Q [pos_q], Q [pos_q + 1]); pos_p = (pos_p + 1) % N;} return ans;} int main () {int I, J, K, Pos; point temp, temp1; while (scanf ("% d", & N, & M )! = EOF) {If (n = 0 & M = 0) return 0; temp. y = 1e8; for (I = 0; I <n; I ++) {scanf ("% lf", & P [I]. x, & P [I]. y); If (P [I]. Y <temp. y) temp = P [I], Pos = I;} p [POS] = P [0], p [0] = temp; temp. y = 1e8; for (I = 0; I <m; I ++) {scanf ("% lf", & Q [I]. x, & Q [I]. y); If (Q [I]. Y <temp. y) temp = Q [I], Pos = I;} Q [POS] = Q [0], Q [0] = temp; qsort (p, n, sizeof (P [0]), cmp_p); qsort (Q, M, sizeof (Q [0]), cmp_q); printf ("%. 5lf \ n ", SQRT (min (find_ans (p, N, Q, m), find_ans (Q, M, P, n);} return 0 ;}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.