bzoj 1038 瞭望塔 半平面交 + 最小值 枚举
来源:互联网 发布:7u分享网络注册 编辑:程序博客网 时间:2024/05/17 21:52
题目来源:
http://61.187.179.132/JudgeOnline/problem.php?id=1038
给出n个点,从 x值较小到较大给出, 连成的一条折线, 求从这折线上一点放一个垂直的杆,在杆顶能看到整个折线。 求杆的最小长度。
分析: 显然杆的最小摆放位置在 折线顶点 或者 半平面交的交点处。
代码如下:
const double EPS = 1e-10 ;const int Max_N = 305 ;const double inf = 1e10 ; // 这个 开小了 1e9 都WA了好几次double add(double a, double b){ return (fabs(a + b) < EPS * (fabs(a) + fabs(b)) ) ? 0 : (a + b );}struct Point { double x, y; Point(){} Point(double x, double y):x(x) , y(y){} Point operator - (Point a){ return Point(add(x , -a.x) , add(y , -a.y)) ; } Point operator + (Point a){ return Point(add(x , a.x) , add(y , a.y)) ; } double operator ^(Point a){ return add(x * a.y , - y * a.x) ; } Point operator * (double d){ return Point(x * d , y * d) ; } void write(){ printf("%lf %lf\n" , x , y) ; }};struct Line{ //有向直线 Point st, ed; Line(){} Line(Point s, Point e){ st = s ; ed = e ; } bool onRight(Point a){ //点a在直线向量的右边 return ((ed - st)^(a - st)) < 0 ; } bool parallel(Line l){ return ((ed -st)^(l.ed - l.st)) == 0 ; } Point Crossnode(Line l){ //两直线的交点 double t = (l.ed - l.st) ^(l.st - st) ; double t1 = (l.ed - l.st)^(ed - st) ; return st + (ed - st)*(t / t1) ; } bool onseg(Point a){ return ((a.x - st.x)*(a.x - ed.x) <EPS) && ((a.y - st.y)*(a.y - ed.y) <EPS) ; } double jijiao(){ return atan2(ed.y - st.y , ed.x - st.x) ; } void write(){ printf("%lf %lf %lf %lf\n" , st.x ,st.y ,ed.x ,ed.y) ; }};//排序函数 [优先顺序:1极角 2. 前面的直线在后面的左边 ]bool operator < (Line l, Line r){ double lp = l.jijiao() ; double rp = r.jijiao() ; if( fabs(lp - rp) > EPS) return lp < rp ; return ((l.st - r.st)^(r.ed - r.st)) < -EPS ;}//用于计算的双端队列Line dequeue[Max_N] ;Point pt[Max_N] ;int halfPanelCross(Line line[] , int ln){ int i, tn; sort(line, line + ln ) ;// 平面在向量左边 的筛选 for(i = tn = 1 ; i < ln ; i++){// 处理极角相同的,选择向量方向最左边的 if(fabs(line[i].jijiao() - line[i -1].jijiao()) > EPS) line[tn++] = line[i] ; } ln = tn ; int bot = 0 , top = 1 ; dequeue[0] = line[0] ; dequeue[1] = line[1] ; for(i = 2 ; i < ln ; i++){ if(dequeue[top].parallel(dequeue[top - 1])|| dequeue[bot].parallel(dequeue[bot + 1])) return 0 ; while(bot < top && line[i].onRight(dequeue[top].Crossnode(dequeue[top - 1]))) top -- ; while(bot < top && line[i].onRight(dequeue[bot].Crossnode(dequeue[bot + 1]))) bot ++ ; dequeue[++ top] = line[i] ; } while(bot < top && dequeue[bot].onRight(dequeue[top].Crossnode(dequeue[top -1]))) top -- ; while(bot < top && dequeue[top].onRight(dequeue[bot].Crossnode(dequeue[bot + 1]))) bot ++ ; if(top <= bot + 1) return 0 ; // 若队列为空, 则空集 int n = 0 ; //计算交点(注意不同直线形成的交点可能重合) 半平面交是凸多边形 for(i = bot ; i < top ; i++) pt[n ++] = dequeue[i].Crossnode(dequeue[i + 1]) ; if(bot < top +1) pt[n ++] = dequeue[bot].Crossnode(dequeue[top]) ; return n ;}Line List[Max_N] ;Point p[Max_N] ;int n;void go(){ int i , j; Point s, t ; Line tmp ; double ans = inf; i = n -1 ; List[i ++] = Line(Point(-inf ,-inf) , Point(inf , -inf)) ; List[i ++] = Line(Point(inf ,-inf) , Point(inf , inf)) ; List[i ++] = Line(Point(inf ,inf) , Point(-inf , inf)) ; List[i ++] = Line(Point(-inf ,inf) , Point(-inf , -inf)) ; int ttn = i ; int tn = halfPanelCross(List , ttn) ; for(i = 0 ; i < n ; i++){ s = p[i] ; t.x = s.x , t.y = 1000 ; for( j = 0 ; j < tn ; j++){ tmp = Line(pt[j] , pt[(j + 1) % tn]) ; Point cross = Line(s ,t).Crossnode(tmp) ; if(tmp.onseg(cross)) ans = min(ans , cross.y - s.y) ; } } for(i = 0 ; i < tn ; i++){ s = pt[i] ; t.x = s.x , t.y = 1000 ; for(j = 0 ; j < n - 1 ; j++){ tmp = Line(p[j] , p[j + 1]) ; Point cross = Line(s,t).Crossnode(tmp) ; if(tmp.onseg(cross)) ans = min(ans , s.y - cross.y) ; } } printf("%.3lf\n" , ans + EPS) ;}int main(){ int i ; while(scanf("%d" , &n) != EOF){ for(i = 0 ; i < n ; i++) scanf("%lf" , &p[i].x) ; for(i = 0 ; i < n ; i++) scanf("%lf" , &p[i].y) ; for(i = 0 ; i < n-1 ; i++){ List[i] = Line(p[i] , p[i + 1]) ; } go() ; }}
0 0
- bzoj 1038 瞭望塔 半平面交 + 最小值 枚举
- BZOJ 1038 ZJOI2008 瞭望塔 半平面交
- BZOJ 1038 ZJOI 2008 瞭望塔 半平面交
- [BZOJ 1038][ZJOI 2008]瞭望塔(半平面交)
- BZOJ 1038 ZJOI2008 瞭望塔 半平面交
- BZOJ 1038: [ZJOI2008]瞭望塔 半平面交
- bzoj 1038: [ZJOI2008]瞭望塔 (半平面交)
- [省选前题目整理][BZOJ 1038][ZJOI 2008]瞭望塔(半平面交)
- [BZOJ1038]ZJOI2008瞭望塔|半平面交
- bzoj1038 瞭望塔 半平面交
- 【bzoj1038】【ZJOI2008】【瞭望塔】【半平面交】
- ZJOI 2008 瞭望塔 半平面交
- ZJOI2008 瞭望塔 半平面交
- [半平面交] BZOJ1038: [ZJOI2008]瞭望塔
- bzoj1038 瞭望塔【半平面交】
- 【半平面交】【计算几何】[BZOJ1038][ZJOI2008]瞭望塔
- 【半平面交】[ZJOI2008][HYSBZ\BZOJ1038]瞭望塔
- [BZOJ1038][ZJOI2008]瞭望塔(半平面交)
- 大数相加
- hdu 2516 FIB博弈模型
- hdu 2897 巴什博弈变形
- hdu 3032 SG(打表找规律) 石子可以 任意取 或分割成非空的两堆
- zoj 3386 Trick or Treat 三分 求最大值的 最小值
- bzoj 1038 瞭望塔 半平面交 + 最小值 枚举
- OpenGL入门学习之八——使用显示列表
- zoj 3233 容斥原理 + 双条件
- kmp变形 如何判断第i个字符是否匹配函数 hdu 4749
- bzoj 2732 [HNOI2012]射箭 半平面交(刘汝佳版不超时) + 整型二分处理
- ioctl()函数详解分类
- 2014北京邀请赛 F Football on Table
- 2012 ICPC/ACM 成都现场赛 Candy
- 线性筛素数的方法