[BZOJ1038][洛谷P2600]-[ZJOI2008]瞭望塔-半平面交
2017-12-05 15:14
471 查看
这恶心的题,细节实在是有点多啊= =….
听说洛谷上的数据好像要苛刻一些,所以也放一个门
洛谷P2600传送门
![](http://img.blog.csdn.net/20171205151318201?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvSXp1bWlfSGFuYWtv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
第一行包含一个整数n,表示轮廓折线的节点数目。接下来第一行n个整数, 为x1 ~ xn. 第三行n个整数,为y1 ~ yn。
输出格式:
包含一个实数,为塔的最小高度,精确到小数点后三位。
正解是半平面交。把相邻村庄之间的连线,只有在连线的一侧可以同时看见两个村庄,很明显是个半平面交。关于半平面交部分,可以参考题目:BZOJ1007水平可见直线 (题目传送门)
很明显瞭望塔要么在转折点处,要么在某个村庄的正上方,建在中间一定不如建在某个端点优。
因此,处理出合法的区域后,枚举每个转折点和村庄,计算建立瞭望塔的高度更新答案。
实现细节比较多
比如答案为-0.000时注意要输出0
还有边界问题,要么在边界加框,要么就要手动算边界点,坐标尽量开得大一点。实现时me写的是后者。
不要eps也可以过,不用太在意eps的问题
题目
BZOJ1038传送门听说洛谷上的数据好像要苛刻一些,所以也放一个门
洛谷P2600传送门
题目大意
H村村长dadzhi决定在村中建立一个瞭望塔,以此加强村中的治安。将H村抽象为平面轮廓折线,用(x1, y1), (x2, y2), …. (xn, yn)来描述H村的形状,这里x1 < x2 < …< xn。瞭望塔可以建造在[x1, xn]间的任意位置, 但必须满足从瞭望塔的顶端可以看到H村的任意位置。在不同的位置建造瞭望塔,所需要建造的高度是不同的。请你写一个程序,帮助dadzhi村长计算塔的最小高度。输入输出格式
输入格式:第一行包含一个整数n,表示轮廓折线的节点数目。接下来第一行n个整数, 为x1 ~ xn. 第三行n个整数,为y1 ~ yn。
输出格式:
包含一个实数,为塔的最小高度,精确到小数点后三位。
解法
多画几个图大概就能看出来做法正解是半平面交。把相邻村庄之间的连线,只有在连线的一侧可以同时看见两个村庄,很明显是个半平面交。关于半平面交部分,可以参考题目:BZOJ1007水平可见直线 (题目传送门)
很明显瞭望塔要么在转折点处,要么在某个村庄的正上方,建在中间一定不如建在某个端点优。
因此,处理出合法的区域后,枚举每个转折点和村庄,计算建立瞭望塔的高度更新答案。
实现细节比较多
比如答案为-0.000时注意要输出0
还有边界问题,要么在边界加框,要么就要手动算边界点,坐标尽量开得大一点。实现时me写的是后者。
不要eps也可以过,不用太在意eps的问题
下面是自带大常数的代码
#include <cmath> #include <cstdio> #include <cstring> #include <algorithm> using namespace std ; const double eps = 1e-9 ; int N ; struct Vector{ double x , y ; double len(){ return sqrt( x * x + y * y ) ; } Vector(){} ; Vector( double x_ , double y_ ) : x(x_) , y(y_){} ; }; typedef Vector Point ; typedef Vector Vv ; int dcmp( const double &x ){ //if( x > -eps && x < eps ) return 0 ; //return ( x > eps ? 1 : -1 ) ; if( x == 0 ) return 0 ; return x > 0 ? 1 : -1 ; } Vv operator + ( const Vv &A , const Vv &B ){ return Vv( A.x + B.x , A.y + B.y ) ; } Vv operator - ( const Vv &A , const Vv &B ){ return Vv( A.x - B.x , A.y - B.y ) ; } Vv operator * ( const Vv &A , const double &p ){ return Vv( A.x * p , A.y * p ) ; } Vv operator / ( const Vv &A , const double &p ){ return Vv( A.x / p , A.y / p ) ; } bool operator ==( const Vv &A , const Vv &B ){ return A.x == B.x && A.y == B.y ; } bool operator < ( const Vv &A , const Vv &B ){ return A.x < B.x || ( A.x == B.x && A.y < B.y ) ; } double Dot ( const Vv &A , const Vv &B ){ return A.x * B.x + A.y * B.y ; } double Cross( const Vv &A , const Vv &B ){ return A.x * B.y - A.y * B.x ; } struct Line{ Point pp ; Vector vv ; double ang ; Line(){} ; Line( Point pp_ , Vector vv_ ): pp(pp_) , vv(vv_){ang = atan2( vv.y , vv.x ) ;} ; bool operator < ( const Line &A ) const { return ang < A.ang ; } }; int fr , ba ; Point a[305] , vtx[305] ; Line La[305] , pne[305] ; Point glt( Point P , Vector u , Point Q , Vector v ){ double t1 = Cross( Q - P , v ) / Cross( u , v ) ; return P + u * t1 ; } void halfPlaneIntersect( Line *La , int siz , Point *p , Line *pne , int &fr , int &ba ){ sort( La + 1 , La + siz + 1 ) ; fr = 1 , ba = 0 ; pne[++ba] = La[1] ; for( int i = 2 ; i <= siz ; i ++ ){ while( ba > fr && dcmp( Cross( p[ba-1] - La[i].pp , La[i].vv ) ) >= 0 ) ba -- ; while( ba > fr && dcmp( Cross( p[fr] - La[i].pp , La[i].vv ) ) >= 0 ) fr ++ ; ++ ba ; pne[ba] = La[i] ; if( dcmp( pne[ba].ang - pne[ba-1].ang ) == 0 ){ ba -- ; if( dcmp( Cross( pne[ba].pp - La[i].pp , La[i].vv ) ) >= 0 ) pne[ba] = La[i] ; } if( ba > fr ) p[ba-1] = glt( pne[ba].pp , pne[ba].vv , pne[ba-1].pp , pne[ba-1].vv ) ; } } void solve(){ for( int i = 1 ; i < N ; i ++ ) La[i] = Line( a[i] , a[i+1] - a[i] ) ; halfPlaneIntersect( La , N - 1 , vtx , pne , fr , ba ) ; double ans = 1e12 ; sort( vtx + fr , vtx + ba + 1 - 1 ) ; a[0] = Point( -1e15 , 0 ) ; a[N+1] = Point( 1e15 , 0 ) ; for( int i = 0 , now = fr ; i <= N && now <= ba - 1 ; i ++ ){ while( now <= ba - 1 && a[i].x <= vtx[now].x && a[i+1].x >= vtx[now].x ){ double len = ( vtx[now].x - a[i].x ) / ( a[i+1].x - a[i].x ) ; ans = min( ans , vtx[now].y - ( a[i].y + ( ( a[i+1] - a[i] ) * len ).y ) ) ; now ++ ; } } vtx[fr-1] = Point( -1e10 , pne[fr].pp.y + ( pne[fr].vv.y / pne[fr].vv.x ) * (-1e10 - pne[fr].pp.x ) ) ; vtx[ba] = Point( 1e10 , pne[ba-1].pp.y + ( pne[ba].vv.y / pne[ba].vv.x ) * ( 1e10 - pne[ba].pp.x ) ) ; for( int i = fr - 1 , now = 1 ; i <= ba - 1 && now <= N ; i ++ ){ while( now <= N && vtx[i].x <= a[now].x && vtx[i+1].x >= a[now].x ){ double len = ( a[now].x - vtx[i].x ) / ( vtx[i+1].x - vtx[i].x ) ; ans = min( ans , ( vtx[i].y + ( ( vtx[i+1] - vtx[i] ) * len ).y ) - a[now].y ) ; now ++ ; } } if( dcmp( ans ) <= 0 ) ans = 0 ; printf( "%.3f" , ans ) ; } int main(){ scanf( "%d" , &N ) ; for( int i = 1 ; i <= N ; i ++ ) scanf( "%lf" , &a[i].x ) ; for( int i = 1 ; i <= N ; i ++ ) scanf( "%lf" , &a[i].y ) ; solve() ; }
相关文章推荐
- BZOJ 1038: [ZJOI2008]瞭望塔 半平面交
- [省选前题目整理][BZOJ 1038][ZJOI 2008]瞭望塔(半平面交)
- [BZOJ1038][ZJOI2008]瞭望塔(半平面交)
- BZOJ 1038 ZJOI2008 瞭望塔 半平面交
- bzoj 1038: [ZJOI2008]瞭望塔 [半平面交]
- [BZOJ 1038][ZJOI 2008]瞭望塔(半平面交)
- [BZOJ1038]ZJOI2008瞭望塔|半平面交
- [BZOJ1038][ZJOI2008]瞭望塔(半平面交)
- bzoj 1038: [ZJOI2008]瞭望塔 (半平面交)
- [BZOJ1038][ZJOI2008]瞭望塔(半平面交)
- 【bzoj1038】【ZJOI2008】【瞭望塔】【半平面交】
- [半平面交] BZOJ1038: [ZJOI2008]瞭望塔
- BZOJ 1038 ZJOI2008 瞭望塔 半平面交
- BZOJ 1038 ZJOI2008 瞭望塔 半平面交
- [BZOJ1038][ZJOI2008]瞭望塔(半平面交)
- bzoj 1038 [ZJOI2008]瞭望塔(半平面交)
- BZOJ 1038 ZJOI 2008 瞭望塔 半平面交
- 【半平面交】bzoj1038 [ZJOI2008]瞭望塔
- 【BZOJ1038】[ZJOI2008]瞭望塔 半平面交
- 【半平面交】【计算几何】[BZOJ1038][ZJOI2008]瞭望塔