[BZOJ1038][洛谷P2600]-[ZJOI2008]瞭望塔-半平面交
来源:互联网 发布:船越文夫 知乎 编辑:程序博客网 时间:2024/05/21 21:08
这恶心的题,细节实在是有点多啊= =….
题目
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() ;}
阅读全文
0 0
- [BZOJ1038][洛谷P2600]-[ZJOI2008]瞭望塔-半平面交
- [BZOJ1038]ZJOI2008瞭望塔|半平面交
- 【bzoj1038】【ZJOI2008】【瞭望塔】【半平面交】
- [半平面交] BZOJ1038: [ZJOI2008]瞭望塔
- 【半平面交】【计算几何】[BZOJ1038][ZJOI2008]瞭望塔
- 【半平面交】[ZJOI2008][HYSBZ\BZOJ1038]瞭望塔
- [BZOJ1038][ZJOI2008]瞭望塔(半平面交)
- bzoj1038:[ZJOI2008]瞭望塔(半平面交)
- [BZOJ1038][ZJOI2008]瞭望塔(半平面交)
- bzoj1038 [ZJOI2008]瞭望塔(半平面交)
- bzoj1038 瞭望塔 半平面交
- bzoj1038 瞭望塔【半平面交】
- 【BZOJ1038】[ZJOI2008]瞭望塔 计算几何 半平面交/模拟退火+二分
- ZJOI2008 瞭望塔 半平面交
- 【BZOJ1038】【codevs1412】瞭望塔,半平面交/三分法
- bzoj1038: [ZJOI2008]瞭望塔
- 【ZJOI2008】【BZOJ1038】瞭望塔
- bzoj1038[ZJOI2008]瞭望塔
- ThinkPHP5的验证码操作
- JScrollPane的使用
- 简单对称加密算法之加密
- This dependency was not found: * !!vue-style-loader!css-loader?……解决方案
- 查看当前网站的cookie的两种快捷方法
- [BZOJ1038][洛谷P2600]-[ZJOI2008]瞭望塔-半平面交
- 锁表清除session
- 使用R语言画三维图
- Matlab图像的几何变换之图像镜像
- 使用Swagger自动生成文档
- 企业管理系统类型有哪些?企业管理系统如何选型?
- 网狐棋牌荣耀6603游戏源码下载安装
- Android Data Binding 配合BaseAdapter
- Linux之设置服务为开机自启动