【BZOJ1038】[ZJOI2008]瞭望塔 半平面交
【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,注意考虑实数误差带来的问题。
题解:首先能看到所有位置的点一定在这些折线的上半平面交上,现在问题就变成了在半平面交和下面的折线上各选择一个横坐标相同的点使得两点间距离最小。因为上下都是折线,那么最小值一定是在某个折线的拐点处取到,那么只需要将这些拐点都扫一遍即可。
为了方便,我们需要添加3条辅助线(上,左,右)来限制边界,注意3条线的斜率不能相同。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long double ld;
const int maxn=310;
const ld eps=1e-10;
int n,m,h,t;
int q[maxn];
ld ans;
struct point
{
ld x,y;
point (){}
point (ld a,ld b){x=a,y=b;}
point operator + (const point &a) const {return point(x+a.x,y+a.y);}
point operator - (const point &a) const {return point(x-a.x,y-a.y);}
ld operator * (const point &a) const {return x*a.y-y*a.x;}
point operator * (const ld &a) const {return point(x*a,y*a);}
}v[maxn],p[maxn];
struct line
{
point p,v;
ld a;
line() {}
line(point x,point y) {p=x,v=y,a=atan2(v.y,v.x);} }l[maxn];
point getp(line l1,line l2)
{
point u=l1.p-l2.p;
ld temp=(l2.v*u)/(l1.v*l2.v);
return l1.p+l1.v*temp;
}
bool onlft(line a,point b)
{
return a.v*(b-a.p)>eps;
}
bool cmpl(line a,line b)
{
if(fabs(a.a-b.a)<eps) return onlft(a,b.p);
return a.a<b.a;
}
bool cmpp(point a,point b)
{
return a.x<b.x;
}
void HPI()
{
sort(l+1,l+n+3,cmpl);
int i,cnt=0;
for(i=2,cnt=1;i<=n+2;i++) if(fabs(l[i].a-l[cnt].a)>eps) l[++cnt]=l[i];
h=t=q[1]=1;
for(i=2;i<=cnt;i++)
{
while(h<t&&onlft(l[i],getp(l[q[t]],l[q[t-1]]))) t--;
while(h<t&&onlft(l[i],getp(l[q[h]],l[q[h+1]]))) h++;
q[++t]=i;
}
while(h<t&&onlft(l[q[h]],getp(l[q[t]],l[q[t-1]]))) t--;
while(h<t&&onlft(l[q[t]],getp(l[q[h]],l[q[h+1]]))) h++;
q[++t]=q[h];
for(i=h;i<t;i++) p[++m]=getp(l[q[i]],l[q[i+1]]);
sort(p+1,p+m+1,cmpp);
}
void calc(point x,point a,point b)
{
point c;
if(fabs(x.x-a.x)<eps) c=a;
else c=a+(b-a)*((x.x-a.x)/(b.x-a.x));
ld dis=fabs(c.y-x.y);
ans=min(ans,dis);
}
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
int main()
{
n=rd();
int i,j;
for(i=1;i<=n;i++) v[i].x=rd();
for(i=1;i<=n;i++) v[i].y=rd();
for(i=1;i<n;i++) l[i]=line(v[i+1],v[i]-v[i+1]);
l[n].p=point(0,1e25),l[n].v=point(1e7,1);
l[n+1].p=point(-1,0),l[n+1].v=point(1,1e25);
l[n+2].p=point(1e7,1e25),l[n+2].v=point(-1e25,-2);
HPI(),ans=1e25;
for(i=1,j=2;i<=n;i++)
{
for(;p[j].x<v[i].x;j++)
calc(p[j],v[i-1],v[i]);
if(j>2)
calc(v[i],p[j-1],p[j]);
}
printf("%.3Lf",ans);
return 0;
}
【BZOJ1038】[ZJOI2008]瞭望塔 半平面交的更多相关文章
- [BZOJ1038][ZJOI2008]瞭望塔(半平面交)
1038: [ZJOI2008]瞭望塔 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2999 Solved: 1227[Submit][Statu ...
- bzoj千题计划126:bzoj1038: [ZJOI2008]瞭望塔
http://www.lydsy.com/JudgeOnline/problem.php?id=1038 本题可以使用三分法 将点按横坐标排好序后 对于任意相邻两个点连成的线段,瞭望塔的高度 是单峰函 ...
- 「BZOJ1038」「洛谷P2600」「ZJOI2008」瞭望塔 半平面交+贪心
题目链接 BZOJ/洛谷 题目描述 致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安. 我们将H村抽象为一维的轮廓.如下图所示: 我们可以用一条山的上方 ...
- bzoj 1038 瞭望塔 半平面交+分段函数
题目大意 给你一座山,山的形状在二维平面上为折线 给出\((x_1,y_1),(x_2,y_2)...(x_n,y_n)\)表示山的边界点或转折点 现在要在\([x_1,x_n]\)(闭区间)中选择一 ...
- [日常摸鱼]bzoj1038 [ZJOI2008]瞭望塔-模拟退火/几何
题意:给一条平面内$n$个点的折线,要求在折线上搞一个高度$h$的瞭望塔,能够看见折线上所有的点,求$h$的最小值($n \leq 300$) updata2018.1.21 正解半平面交在另一篇里面 ...
- bzoj1038: [ZJOI2008]瞭望塔
Description 致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安.我们将H村抽象为一维的轮廓.如下图所示 我们可以用一条山的上方轮廓折线(x1, ...
- BZOJ-1038 [ZJOI2008]瞭望塔
先求半平面交,然后建塔的地方肯定是在半平面交的交点上或者是在地面线段的交点上. #include <cstdlib> #include <cstdio> #include &l ...
- [日常摸鱼]bzoj1038[ZJOI2008]瞭望塔-半平面交
这回好好用半平面交写一次- 看了cls当年写的代码看了好久大概看懂了-cls太强辣 #include<cstdio> #include<iostream> #include&l ...
- 【半平面交】bzoj1038 [ZJOI2008]瞭望塔
http://m.blog.csdn.net/blog/qpswwww/44105605 #include<cstdio> #include<cmath> #include&l ...
随机推荐
- ubuntu16.04 ssh服无法远程连接解决办法
1.安装ssh服务sudo apt-get install openssh-server 2.修改配置文件sudo vi /etc/ssh/sshd_config#PermitRootLogin wi ...
- Window mode
D3D window mode:Upper left (0,0)是左上角 OGL window mode:Lower left(0,0)是左下角 nvn API nvn::Device::SetWin ...
- ES6中Set集合(与java里类似)
一.引入背景 Set集合是一种无重复元素的列表,开发者们一般不会逐一读取数组中的元素,也不太可能逐一访问Set集合中的每个元素,通常的做法是检测给定的值在某个集合中是否存在 Map集合内含多组键值对, ...
- zookeeper启动错误 ---- Unable to load database on disk
zk启动报错 解决办法,进入zkdata目录删除version-2下面的所有文件 参考: https://issues.apache.org/jira/browse/ZOOKEEPER-1546 [h ...
- Linux增加挂载盘
命令:fdisk /dev/sdb, m 命令:m,n,e,1,p,w 命令:mkfs -t ext4 /dev/sdb,y 挂载命令:mount -t ext4 /dev/sdb /data 获取U ...
- sersync+rsync实时数据同步
sersync+rsync实时数据同步 1.相关背景介绍 前面有关文章配置实现了rsync增量同步以及配置为定时同步,但是在实际生产环境中需要实时的监控数据从而进行同步(不间断同步),可以采取inot ...
- SQL JOB 调用 SSIS package 权限问题
来自: http://www.cnblogs.com/sodacc/archive/2012/11/26/2789135.html 第一次用SQL给SSIS包排JOB的时候,都会遇到这样一个问题:单独 ...
- Android学习(二十三)SubMenu 子菜单
一.SubMenu子菜单 和功能菜单相似,但是可以添加子菜单. 二.实现步骤: 1.通过onCreateOptionsMenu方法创建子菜单,可以通过代码动态创建,也可以通过xml进行创建. 2.通过 ...
- 推荐系统学习(2)——基于TF-IDF的改进
使用用户打标签次数*物品打标签次数做乘积的算法尽管简单.可是会造成热门物品推荐的情况.物品标签的权重是物品打过该标签的次数,用户标签的权重是用户使用过该标签的次数.从而导致个性化的推荐减少,而造成热门 ...
- 一个队列类的实现(比delphi自带的速度快70倍)(线程安全版本)
unit sfContnrs; interface {$DEFINE MULTI_THREAD_QUEUE} //线程安全版本,如果不需要线程安全,请注释掉此行代码 {$IFDEF MULTI_THR ...