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

AC牛的题目,精度比较恶心,最后一组数据一个误差是0.00006 我精度用了1e-8,而标程是1e-4,卡死在最后一组数据上了。。。
这题看起来是三维的几何,其实完全可以压缩到二维来做。

  1// Author : AmazingCaddy
  2//
  3#include<iostream>
  4#include<cstdio>
  5#include<cstring>
  6#include<algorithm>
  7#include<vector>
  8#include<cmath>
  9#include<complex>
 10using namespace std;
 11
 12typedef complex<double> point;
 13const double eps = 1e-4;
 14const double inf = 1e20;
 15const double pi  = acos( -1.0 );
 16const double g = 9.18;
 17
 18double operator ^ ( const point p1, const point p2 ) return imag( conj( p1 ) * p2 ); }
 19double operator & ( const point p1, const point p2 ) return real( conj( p1 ) * p2 ); }
 20int dblcmp( double x ) return ( x < -eps ? -1 : x > eps ); }
 21
 22struct line
 23{
 24    point a, b;
 25    line( ){ }
 26    line( point u, point v ) : a( u ) , b( v ) {  }
 27}
;
 28
 29struct POLY
 30{
 31    point p[12];
 32    int n, type;
 33    double h, k;
 34}
poly[12];
 35
 36bool cmp( const POLY & a, const POLY & b ) return ( a.h == b.h && a.type < b.type ) || a.h > b.h; }
 37
 38point operator*( line l0, line l1 )
 39{
 40    double t = l0.a - l1.a^ l0.b - l1.a;
 41    double s = l0.b - l1.b^ l0.a - l1.b;
 42    return l1.a + ( l1.b - l1.a ) * t / ( t + s );
 43}

 44
 45//  不是逆时针,转化成逆时针的
 46void changeclockwise( POLY & P )
 47{
 48    int pn = P.n;
 49    if( ( P.p[1- P.p[0^ P.p[2- P.p[0] ) < 0 )
 50        forint i = 0; i < pn / 2; i++ )
 51            swap( P.p[i], P.p[pn-1-i] );
 52}

 53
 54bool point_on_segment( const point & p, const line & l )
 55{
 56    if( dblcmp( l.a - p ^ l.b - p ) ) return false;
 57    if( dblcmp( l.a - p & l.b - p ) <= 0 ) return true;
 58    return false;
 59}

 60
 61bool segment_cross( const line & l1, const line l2 )
 62{
 63    point p1 = l1.a, p2 = l1.b, p3 = l2.a, p4 = l2.b;
 64    if( ( dblcmp( p2 - p1 ^ p3 - p1 ) ^ dblcmp( p2 - p1 ^ p4 - p1 ) ) == -2 && 
 65        ( dblcmp( p4 - p3 ^ p1 - p3 ) ^ dblcmp( p4 - p3 ^ p2 - p3 ) ) == -2 )
 66        return true;
 67    return false;
 68}

 69
 70bool PointInPoly( const point & p, const POLY & Q )
 71{
 72    int qn = Q.n;
 73    double area1 = 0, area2 = 0;
 74    forint i = 0; i < qn; i++ )
 75        area1 = area1 + ( Q.p[i] ^ Q.p[i+1] );
 76    forint i = 0; i < qn; i++ )
 77        area2 = area2 + fabs( Q.p[i] - p ^ Q.p[i+1- p );
 78    if( dblcmp( fabs( area1 ) - area2 ) == 0 )
 79        return true;
 80    return false;
 81}

 82
 83point seg_cross_poly( line l, const POLY & Q )
 84{
 85    int qn = Q.n;
 86    point s;
 87    forint i = 0; i < qn; i++ )
 88    {
 89        line l1 = line( Q.p[i], Q.p[i+1] );
 90        if( dblcmp( l.a - l.b ^ l1.a - l1.b ) != 0 )
 91        {
 92            s = l * l1;
 93            if( point_on_segment( s, l1 ) && dblcmp( s - l.a & l.b - l.a ) > 0 && !point_on_segment( s, l ) )
 94                break;
 95        }

 96    }

 97    return s;
 98}

 99
100void solve( )
101{
102    int n;
103    double vx, vy, H, x, y,TIME;
104    scanf("%lf%lf%lf",&vx,&vy,&H);
105    point v( vx, vy ), s( 00 );  // v 速度矢量,s 位移矢量
106    point s0;
107    scanf("%d",&n);
108    forint i = 0; i < n; i++ )
109    {
110        scanf("%lf%d",&poly[i].h,&poly[i].n);
111        forint j = 0; j < poly[i].n; j++ )
112        {
113            scanf("%lf%lf",&x,&y);
114            poly[i].p[j] = point( x, y );
115        }

116        changeclockwise( poly[i] );
117        poly[i].p[poly[i].n] = poly[i].p[0];
118        scanf("%d%lf",&poly[i].type,&poly[i].k);
119    }

120
121    poly[n].n = 4; poly[n].h = 0; poly[n].type = 3; poly[n].k = 0;
122    poly[n].p[0= point( 1e8, 1e8 );
123    poly[n].p[1= point( -1e8, 1e8 );
124    poly[n].p[2= point( -1e8, -1e8 );
125    poly[n].p[3= point( 1e8, -1e8 );
126    poly[n].p[4= point( 1e8, 1e8 );
127    n++;
128    sort( poly, poly + n, cmp );
129
130    if( dblcmp( H ) < 0 )
131    {
132        printf("Forever!\n");
133        return ;
134    }

135    TIME = 0.0;
136    forint i = 0; i < n; i++ )
137    {   
138        double h = poly[i].h;
139        double k = poly[i].k;
140        if( h == 0 )
141        {
142            TIME += sqrt( 2 * ( H - h ) / g );
143            printf("%.2lf\n",TIME);
144            return ;
145        }

146        if( H < h ) continue;
147        double time = sqrt( 2 * ( H - h ) / g );
148        s0 = s + v * time;
149        if( PointInPoly( s0, poly[i] ) )
150        {
151            s = s0;
152            TIME += time;
153            H = h;
154            switch( poly[i].type )
155            {
156            case 0:
157                v = v * point( cos( k ), sin( k ) );
158                break;
159
160            case 1:
161                v = point( k, imag( v ) );
162                break;
163
164            case 2:
165                v = point( real( v ), k );
166                break;
167            }

168            if( dblcmp( abs( v ) ) == 0 ) 
169            {   
170                printf("Forever!\n");
171                return ;
172            }

173            point z = seg_cross_poly( line( s, s + v ), poly[i] );
174            TIME = TIME + abs( z - s ) / abs( v );
175            s = z;
176        }

177    }

178}

179
180int main( )
181{
182    int t;
183    //freopen("in","r",stdin);
184    //freopen("out.txt","w",stdout);
185    scanf("%d",&t);
186    forint i = 1; i <= t; i++ )
187    {
188        printf("Case %d: ",i);
189        solve( );
190    }

191    return 0;
192}