计算几何。。首先题意很难懂,多亏了纬哥解释,才懂。。
就是有左边有一条折线,右边有一条折线,两条折线的起点和终点的纵坐标相同,还有一些摄像头,一条线段平行x轴的线段从起点到终点,必须得在两条折线中间,并且不能碰到摄像头,问线段最长的长度
其实不难的,思路很快就有了,先o(n)处理左边折线的点到右边的折线的水平长度以及右边的点到左边的点的长度,然后再求摄像头到左右两条折线的水平长度。。不过wa了,我们很快发现了错误在哪,就是摄像头的纵坐标有可能相同,还有y轴坐标大于或者小于折线的终点和起点的摄像头都不能算进去,不过最后还是写挫了,没有ac,今天终于ac了。。
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <map> using namespace std; #define LL long long #define eps 1e-12 #define mnx 100020 #define mxe 2000020 #define inf 1e12 #define Pi acos( -1.0 ) //精度 int dcmp( double x ){ if( fabs( x ) < eps ) return 0; return x < 0 ? -1 : 1; } // 点 struct point{ double x, y; point( double x = 0, double y = 0 ) : x(x), y(y) {} point operator + ( const point &b ) const{ return point( x + b.x, y + b.y ); } point operator - ( const point &b ) const{ return point( x - b.x, y - b.y ); } point operator * ( const double &k ) const{ return point( x * k, y * k ); } point operator / ( const double &k ) const{ return point( x / k, y / k ); } bool operator < ( const point &b ) const{ return dcmp( y - b.y ) < 0 || dcmp( y - b.y ) == 0 && dcmp( x - b.x ) < 0; } bool operator == ( const point &b ) const{ return dcmp( x - b.x ) == 0 && dcmp( y - b.y ) == 0; } double len(){ return sqrt( x * x + y * y ); } void input(){ scanf( "%lf%lf", &x, &y ); } }; typedef point Vector; // 点积 double dot( Vector a, Vector b ){ return a.x * b.x + a.y * b.y; } // 叉积 double cross( Vector a, Vector b ){ return a.x * b.y - a.y * b.x; } int n, m, q; point a[mnx], b[mnx], c[mnx]; double calc( point p0, point p1, point p2 ){ if(dcmp(p1.y - p2.y) == 0) { return min((p0 - p1).len(), (p0 - p2).len()); } if( p1.y > p2.y ) swap( p1, p2 ); double t = (p0.y - p1.y) / ( p2.y - p1.y ); point v = p1 + ( p2 - p1 ) * t; return ( p0 - v ).len(); } void solve(){ double ans = inf; int j = 0; for( int i = 0; i < n; i++ ){ while( j < m-1 ){ if( dcmp(a[i].y-b[j].y) >= 0 && dcmp(a[i].y-b[j+1].y) <= 0 ){ ans = min( ans, calc( a[i], b[j], b[j+1] ) ); break; } else j++; } } j = 0; for( int i = 0; i < m; i++ ){ while( j < n-1 ){ if( dcmp(b[i].y-a[j].y) >= 0 && dcmp(b[i].y-a[j+1].y) <= 0 ){ ans = min( ans, calc( b[i], a[j], a[j+1] ) ); break; } else j++; } } sort( c, c + q ); int cnt = 0; for( int i = 0; i < q; i++ ){ if( dcmp(c[i].y-a[0].y) < 0 || dcmp(c[i].y-a[n-1].y) > 0 ) continue; c[cnt++] = c[i]; } q = cnt; int i = 0; j = 0; for( int k = 0; k < q; k++ ){ double res = -inf; int cur = k; while( cur < q && dcmp(c[cur+1].y - c[cur].y) == 0 ) cur++; int tmp = cur; while( i < n-1 ){ if( dcmp(c[k].y-a[i].y) >= 0 && dcmp(c[k].y-a[i+1].y) <= 0 ) break; else i++; } while( j < m-1 ){ if( dcmp(c[k].y-b[j].y) >= 0 && dcmp(c[k].y-b[j+1].y) <= 0 ) break; else j++; }//cout << k << " " << cur << endl; for( int u = k; u < cur; u++ ){ if( cross( c[u] - a[i], a[i+1] - a[i] ) < 0 ) k++; else break; } for( int u = cur; u > k; u-- ){ if( cross( c[u] - b[j], b[j+1] - b[j] ) > 0 ) cur--; else break; } res = max( res, calc( c[k], a[i], a[i+1] ) ); res = max( res, calc( c[cur], b[j], b[j+1] ) ); //printf( "%.5lf\n", res ); for( int u = k; u < cur; u++ ){ res = max( res, ( c[u+1] - c[u] ).len() ); } ans = min( res, ans ); k = tmp; } printf( "%.8lf\n", ans ); } int main(){ while( scanf( "%d", &n ) != EOF ){ for( int i = 0; i < n; i++ ) a[i].input(); scanf( "%d", &m ); for( int i = 0; i < m; i++ ) b[i].input(); scanf( "%d", &q ); for( int i = 0; i < q; i++ ) c[i].input(); solve(); } return 0; }
附数据
4
0 0
5 5
9 12
8 15
4
8 0
11 7
12 10
12 15
7
7 4
5 8
6 8
9 8
11 8
14 8
16 8
answer: 2.28571429
时间: 2024-10-09 06:35:58