bzoj1038: [ZJOI2008]瞭望塔
Description
致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安。我们
将H村抽象为一维的轮廓。如下图所示 我们可以用一条山的上方轮廓折线(x1, y1), (x2, y2), …. (xn, yn)来描
述H村的形状,这里x1 < x2 < …< xn。瞭望塔可以建造在[x1, xn]间的任意位置, 但必须满足从瞭望塔的顶端可
以看到H村的任意位置。可见在不同的位置建造瞭望塔,所需要建造的高度是不同的。为了节省开支,dadzhi村长
希望建造的塔高度尽可能小。请你写一个程序,帮助dadzhi村长计算塔的最小高度。
Input
第一行包含一个整数n,表示轮廓折线的节点数目。接下来第一行n个整数, 为x1 ~ xn. 第三行n个整数,为y1
~ yn。
Output
仅包含一个实数,为塔的最小高度,精确到小数点后三位。
Sample Input
6
1 2 4 5 6 7
1 2 2 4 2 1
【输入样例二】
4
10 20 49 59
0 10 10 0
Sample Output
1.000
【输出样例二】
14.500
HINT
N ≤ 300,输入坐标绝对值不超过106,注意考虑实数误差带来的问题。
题解:
说实话一开始没看出是半平面交,后来看题解的图才发现。
看图yy一下可以发现,每相邻两个点组成的所有直线,若想要塔可以看到所有点,塔必须在凸壳上,或者在山顶。
所以我们先求出凸壳,在枚举凸壳上的点到村庄的距离。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#define eps 1e-11
#define inf 1000000000
const int N=1105;
using namespace std;
int n;
struct node{double x,y;
}p[N],sb[N];int pl;
struct node2{node p1,p2;double angle;node2(){}node2(double x1,double y1,double x2,double y2){p1.x=x1;p1.y=y1;p2.x=x2;p2.y=y2;}void get_angle(){angle=atan2(p2.y-p1.y,p2.x-p1.x);}
}seg[N],sa[N],ss[N];int cnt=0,st,ed;
void init()
{p[0].x=p[1].x;p[0].y=100001;p[n+1].x=p[n].x;p[n+1].y=100001;for(int i=1;i<=n;i++){seg[++cnt]=node2(p[i].x,p[i].y,p[i+1].x,p[i+1].y),seg[cnt].get_angle();seg[++cnt]=node2(p[i-1].x,p[i-1].y,p[i].x,p[i].y),seg[cnt].get_angle();}
}
double mulit(node p1,node p2,node p0)
{double x1=p1.x-p0.x,y1=p1.y-p0.y;double x2=p2.x-p0.x,y2=p2.y-p0.y;return x1*y2-x2*y1;
}
bool satify(node x,node2 y)
{if(mulit(x,y.p2,y.p1)<=eps) return true;return false;
}
bool cmp(node2 x,node2 y)
{if(x.angle<y.angle) return true;if(fabs(x.angle-y.angle)<eps&&satify(x.p1,y)==true) return true;return false;
}
node jd(node2 x,node2 y)
{node p1=x.p1,p2=x.p2,p3=y.p1,p4=y.p2,p;double t1=mulit(p1,p4,p3);double t2=mulit(p2,p4,p3);p.x=(t1*p2.x-t2*p1.x)/(t1-t2);p.y=(t1*p2.y-t2*p1.y)/(t1-t2);return p;
}
void work()
{sort(seg+1,seg+cnt+1,cmp);int tp=1;for(int i=2;i<=cnt;i++)if(seg[i].angle-seg[tp].angle>eps) seg[++tp]=seg[i];cnt=tp;sa[1]=seg[1];sa[2]=seg[2];st=1,ed=2;for(int i=3;i<=cnt;i++){while(st<ed&&satify(jd(sa[ed],sa[ed-1]),seg[i])==false) ed--;while(st<ed&&satify(jd(sa[st],sa[st+1]),seg[i])==false) st++;sa[++ed]=seg[i];}while(st<ed&&satify(jd(sa[ed],sa[ed-1]),seg[st])==false) ed--;while(st<ed&&satify(jd(sa[st],sa[st+1]),seg[ed])==false) st++;pl=0;for(int i=st;i<ed;i++) sb[++pl]=jd(sa[i],sa[i+1]);
}
void get_ans()
{double ans=1e60;for(int k=1;k<=pl;k++)for(int i=1;i<n;i++){node t;t.x=sb[k].x;t.y=-1;if(sb[k].x>=p[i].x&&sb[k].x<=p[i+1].x){ss[1]=node2(p[i].x,p[i].y,p[i+1].x,p[i+1].y);ss[2]=node2(t.x,t.y,sb[k].x,sb[k].y);ans=min(ans,sb[k].y-jd(ss[1],ss[2]).y);//printf("%.2lf\n",ans);}}for(int k=1;k<=n;k++)for(int i=1;i<pl;i++){node t;t.x=p[k].x;t.y=-1;if(p[k].x>=sb[i].x&&p[k].x<=sb[i+1].x){ ss[2]=node2(t.x,t.y,p[k].x,p[k].y);ss[1]=node2(sb[i].x,sb[i].y,sb[i+1].x,sb[i+1].y);ans=min(ans,jd(ss[1],ss[2]).y-p[k].y);}}printf("%.3lf",ans);
}
int main()
{scanf("%d",&n);for(int i=1;i<=n;i++) scanf("%lf",&p[i].x);for(int i=1;i<=n;i++) scanf("%lf",&p[i].y);init();work();get_ans();
}
bzoj1038: [ZJOI2008]瞭望塔相关推荐
- bzoj1038 [ZJOI2008]瞭望塔(半平面交)
bzoj1038 [ZJOI2008]瞭望塔 原题地址:http://www.lydsy.com/JudgeOnline/problem.php?id=1038 题意: 村中要建立一个瞭望塔,我们将H ...
- bzoj千题计划126:bzoj1038: [ZJOI2008]瞭望塔
http://www.lydsy.com/JudgeOnline/problem.php?id=1038 本题可以使用三分法 将点按横坐标排好序后 对于任意相邻两个点连成的线段,瞭望塔的高度 是单峰函 ...
- bzoj1038 [ZJOI2008]瞭望塔
Description 致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安.我们 将H村抽象为一维的轮廓.如下图所示 我们可以用一条山的上方轮廓折线(x1 ...
- [BZOJ1038][ZJOI2008]瞭望塔(半平面交)
题目: 我是超链接 题解: 很显然,只有瞭望塔和每个山顶形成直线的斜率的绝对值大于对应山坡的斜率,这个山坡才能看见.不难想到对所有的山坡求一个半平面交然后找到有山顶存在的部分,这个n<=300也 ...
- bzoj1038 [ZJOI2008]瞭望塔 枚举
这个题实际上求的是半个凸包的核,但只需要枚举直线两两交点和地上的点就可以很快跑过 根据线性规划原理答案应该在直线交点上,为什么还要看地上的点? 因为实际上可行域是有下限的,有可能下限与地线重合 码(注 ...
- [BZOJ1038]ZJOI2008瞭望塔|半平面交
考虑某个村庄可以被看见的区域,发现一条线段的上方就是可以看见端点的区域,那就把所有线段扔进去做半平面交,不要忘记了要加上两条左右边界..求出来之后发现答案要么是某个村庄往上到半平面交的一段距离,要么是 ...
- 【BZOJ 1038】 1038: [ZJOI2008]瞭望塔
1038: [ZJOI2008]瞭望塔 Description 致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安.我们 将H村抽象为一维的轮廓.如下图所 ...
- bzoj 1038 [ZJOI2008]瞭望塔
1038: [ZJOI2008]瞭望塔 Time Limit: 10 Sec Memory Limit: 162 MB Submit: 2438 Solved: 1004 [Submit][Sta ...
- luogu P2600 [ZJOI2008]瞭望塔
luogu P2600 [ZJOI2008]瞭望塔 大意 题目讲得很清楚啊 题解 可以发现,那个点一定是某两条直线的交点 然后直接枚举两条直线就好了 // luogu-judger-enable-o2 ...
最新文章
- 随着计算机多媒体技术的产生和发展,多媒体技术及其应用与发展论文(本科)10...
- 从青铜到王者的路线,java枚举类使用场景
- 解决jodconverter 2.2.1 版本不支持docx、xlsx、pptx 转换成PDF格式异常
- app 后台_uni星茫UI V3.0更新uni-app多端小程序源码丸子插件wordpress后台
- 神经网络的输出层有哪些_深度学习的数学-神经网络、输入层、隐藏层、输出层...
- c语言不定参数的使用,C语言中不定参数的实现
- 图解clientWidth,offsetWidth,scrollWidth,scrollTop
- matlab深度学习基本操作,深度学习讲解,源代码分享,用一用改一改随便发篇EI
- Proteus十字路口交通灯
- React Native 填坑记录01
- 软件系统设计-1-软件设计原则
- 计算机 键盘启动,键盘开机如何打开键盘
- “HEAP:Invalid Address specified to RtlValidateHeap( 000D0000, 019FEF18 )错误
- 单片机作业1_为OLED制作汉字字库_第3部分
- 怎么关闭windows中不在控制面板上的smartscreen筛选器
- 【自动化】车间自动化十大必备装置!
- Android颜色对照表
- KPI、KPA、OKR
- 宠物狗网页制作作业 保护动物网页设计模板 简单学生网页设计 静态HTML CSS网站制作成品
- javascript实现电话号码验证