http://124.205.79.250/JudgeOnline/problem?id=3608

旋转卡壳的经典题目,看着网上某篇论文写的,写了一个下午还是WA,最后参考了了haozi的代码,还是WA,原来haozi的代码中将平行跟其中一种情况合并在一起写了,精度调得很高,但是我的精度太低了,调整精度之后过了。但是我觉得这题的精度是不用那么高的,原因应该是出在了,两种情况的合并上面,后来我改成三种情况,精度就1e-8过了,看来是那哥问题。代码如下:
pku 3608
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<vector>
  5 #include<cstring>
  6 #include<complex>
  7 using namespace std;
  8 typedef complex<double> point;
  9 const double eps = 1e-8;
 10 const double pi = acos( -1.0 );
 11 const double inf = 1e100;
 12 vector<point> P, Q;
 13 
 14 double operator ^const point p1, const point p2 ) { return imag( conj( p1 ) * p2 ); }
 15 double operator &const point p1, const point p2 ) { return real( conj( p1 ) * p2 ); }
 16 int dblcmp( double x ) { return ( x < -eps ? -1 : x > eps ); }
 17 double min( double x, double y ) { return ( x < y ? x : y ); }
 18 
 19 double DisPointToSeg( const point & p, const point & p1, const point & p2 )
 20 {
 21     if( dblcmp( p - p1 & p2 - p1 ) < 0 || dblcmp( p - p2 & p1 - p2 ) < 0 )
 22         return min( abs( p1 - p ), abs( p2 - p ) );
 23     return fabs( p1 - p ^ p2 - p ) / abs( p1 - p2 );
 24 }
 25 
 26 double DisPallSeg( point p1, point p2, point p3, point p4 )
 27 {
 28     return min( min( DisPointToSeg( p1, p3, p4 ), DisPointToSeg( p2, p3, p4 ) ),
 29                 min( DisPointToSeg( p3, p1, p2 ), DisPointToSeg( p4, p1, p2 ) ) );
 30 }
 31 
 32 void changeclockwise( vector<point> & g )
 33 {
 34     int n = g.size( );
 35     if( ( g[1- g[0^ g[2- g[0] ) < 0 ) 
 36         forint i = 0; i < n / 2; i++ )
 37             swap( g[i], g[n-1-i] );
 38 }
 39 
 40 double RC( )
 41 {
 42     point f0( 1.00 ), f1( -1.00 );
 43     point p0, p1, p2, p3;
 44     int pn = P.size( ), qn = Q.size( ), k1 = -1, k2 = -1;
 45     double ymin = inf,  ymax = -inf, angle, ang, ans;
 46     
 47     changeclockwise( P );
 48     changeclockwise( Q );
 49     
 50     forint i = 0; i < pn; i++ )
 51         if( ymin > imag( P[i] ) ) ymin = imag( P[i] ), k1 = i;
 52     forint i = 0; i < qn; i++ )
 53         if( ymax < imag( Q[i] ) ) ymax = imag( Q[i] ), k2 = i;
 54     
 55     angle = 0.0;
 56     ans = inf;
 57     
 58     while( angle <= 140 )
 59     {
 60         p0 = P[k1]; p1 = P[(k1+1)%pn];
 61         p2 = Q[k2]; p3 = Q[(k2+1)%qn];
 62         int t = dblcmp( p1 - p0 ^ p3 - p2 );
 63         if( t > 0 ) // 旋转 p2p3
 64         {
 65             ang = arg( ( p3 - p2 ) / f1 );
 66             f1 = p3 - p2;
 67             f0 = -f1;
 68             k2 = ( k2 + 1 ) % qn;
 69             ans = min( ans, DisPointToSeg( p0, p2, p3 ) );
 70         }
 71         else if( t == 0 )
 72         {
 73             ang = arg( ( p1 - p0 ) / f0 );
 74             f0 = p1 - p0;
 75             f1 = -f0;
 76             k1 = ( k1 + 1 ) % pn;
 77             k2 = ( k2 + 1 ) % qn;
 78             ans = min( ans, DisPallSeg( p0, p1, p2, p3 ) );   
 79         }
 80         else // 平行 && 旋转 p0p1, 两种情况可以合并
 81         {
 82             ang = arg( ( p1 - p0 ) / f0 );
 83             f0 = p1 - p0;
 84             f1 = -f0;
 85             k1 = ( k1 + 1 ) % pn;
 86             ans = min( ans, DisPointToSeg( p2, p0, p1 ) );
 87         }
 88         angle += ( ang < 0 ? ang + 2 * pi : ang );
 89     }
 90     return ans;
 91 }
 92 
 93 int main( )
 94 {
 95     int n, m;
 96     double x, y, ans;
 97     while( scanf("%d%d",&n,&m) && ( n + m ) )
 98     {
 99         P.clear( );
100         Q.clear( );
101         forint i = 0; i < n; i++ )
102         {
103             scanf("%lf%lf",&x,&y);
104             P.push_back( point( x, y ) );
105         }
106         forint i = 0; i < m; i++ )
107         {
108             scanf("%lf%lf",&x,&y);
109             Q.push_back( point( x, y ) );
110         }
111         ans = RC( );
112         printf("%.5lf\n",ans);
113     }
114 }