http://www.acm.cs.ecnu.edu.cn/problem.php?problemid=1990 题目的意思是求出一些点,使得这些点到给定的一些直线的距离相等,只有一个点的时候输出该点,多个点那么输出"Many",没有符合的点那么输出"None",大致的做法是:先用角平分线求出一定量的点(最多4个),然后枚举检查这些点,精度有点搞!!!
#include<iostream> #include<complex> #include<cmath> #include<algorithm> using namespace std; typedef complex<double> point;
const double eps = 1e-8; const double inf = 1e20; const double pi = acos( -1.0 ); const int maxn = 103; struct line { point a, b; line( ){ } line( point u, point v ) : a( u ), b( v ) { } }; line L[maxn]; bool vis[maxn];
int dblcmp( double x ){ return ( x < -eps ? -1 : x > eps ); } double operator^( point p1, point p2 ){ return imag( conj( p1 ) * p2 ); } // 叉积 double operator&( point p1, point p2 ){ return real( conj( p1 ) * p2 ); } // 点积 // 两直线交点,求交点之前先判断是否平行 point operator*( line u, line v ) { double t = v.a - u.a ^ v.b - u.a; double s = v.b - u.b ^ v.a - u.b; return u.a + ( u.b - u.a ) * t / ( t + s ); } // 点到直线的距离 double DisPointToLine( point p, line l ){ return fabs( l.a - p ^ l.b - p ) / abs( l.a - l.b ); } // 判断两直线平行 bool LineParallel( line u, line v ) { return dblcmp( ( u.a - u.b ^ v.a - v.b ) ) == 0; } // 直线向左侧平移 line Translation( line l ) { point p = ( l.b - l.a ) * point( 0.0, 1000.0 / abs( l.b - l.a ) ); return line( l.a + p, l.b + p ); } // 以l.a为原点,逆时针旋转90度 line Rotation( line l ) { point p = ( l.b - l.a ) * point( 0.0, 1.0 ); return line( l.a, l.a + p ); } // 求 u 与 v 的一条角平分线 line GetLine( line u, line v ) { line l1 = Translation( u ); line l2 = Translation( v ); return line( u * v, l1 * l2 ); }
bool check( point p, int n, double val ) { int i; double D; for( i = 0; i < n; i++ ) { D = DisPointToLine( p, L[i] ); if( dblcmp( D - val ) != 0 )return false; } return true; }
bool same_point( point p1, point p2 ) { return dblcmp( imag( p1 ) - imag( p2 ) ) == 0 && dblcmp( real( p1 ) - real( p2 ) ) == 0; }
int MyUnique( point p[], int n ) { int i, len = 1; for( i = 1; i < n; i++ ) { if( !same_point( p[i], p[i-1] ) ) p[len++] = p[i]; } return len; }
void solve( int n ) { if( n < 3 ){ printf("Many\n"); return; } int i, j; line l[4], u, v, w; memset( vis, false, sizeof( vis ) ); vis[0] = true; u = L[0]; for( i = 1; i < n; i++ ) { if( !LineParallel( L[0], L[i] ) ) { vis[i] = true; v = L[i]; break; } } if( i == n ){ printf("None\n"); return; } l[0] = GetLine( u, v ); l[1] = Rotation( l[0] ); for( i = 1; i < n; i++ ) { if( !vis[i] && ( !LineParallel( u, L[i] ) || !LineParallel( v, L[i] ) ) ) { vis[i] = true; w = L[i]; break; } } if( !LineParallel( u, w ) ) { l[2] = GetLine( u, w ); l[3] = Rotation( l[2] ); } else { l[2] = GetLine( v, w ); l[3] = Rotation( l[2] ); } point p[4]; double val[4]; int len = 0; if( !LineParallel( l[0], l[2] ) ) { p[len] = l[0] * l[2]; val[len++] = DisPointToLine( p[len], u ); } if( !LineParallel( l[0], l[3] ) ) { p[len] = l[0] * l[3]; val[len++] = DisPointToLine( p[len], u ); } if( !LineParallel( l[1], l[2] ) ) { p[len] = l[1] * l[2]; val[len++] = DisPointToLine( p[len], u ); } if( !LineParallel( l[1], l[3] ) ) { p[len] = l[1] * l[3]; val[len++] = DisPointToLine( p[len], u ); } len = MyUnique( p, len ); int cnt = 0; point P; for( i = 0; i < len; i++ ) { if( check( p[i], n, val[i] ) ) { P = p[i]; cnt++; } } if( cnt == 0 )printf("None\n"); else if( cnt == 1 )printf("%.5lf %.5lf\n",P.real( ), P.imag( ) ); else printf("Many\n"); }
int main( ) { int i, n; double x1, x2, y1, y2; while( scanf("%d",&n) != EOF ) { for( i = 0; i < n; i++ ) { scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); L[i] = line( point( x1, y1 ), point( x2, y2 ) ); } solve( n ); } return 0; }
|