【BZOJ】【1038】【ZJOI2008】瞭望塔
计算几何/半平面交
说是半平面交,实际上只是维护了个下凸壳而已……同1007水平可见直线
对于每条线段,能看到这条线段的点都在这条线段的“上方”,那么对所有n-1条线段求一个可视区域的交,就是求一个半平面交……(好扯)
一开始我想的是:直接找到这个下凸壳的最低点,它的y值就是答案辣~但是明显不对>_>这题让求的是塔的最低高度……不光要考虑塔顶,还要看塔底的啊!
那么我们怎么找呢?我们可以发现:随着x的变化,塔高(就是地面到凸壳的竖直距离,y坐标之差)是一个分段函数,分段点就是地面的折点以及凸壳的顶点!而且在每一段里面,塔高的值是一个一次函数!经过大胆猜想,小(bu)心(yong)证明我们发现:分段一次函数的极值在分段点和边界点处取到。
那么就是对这些点算一下答案就可以了……点数是O(n)的……
![](/assets/blank.gif)
![](/assets/blank.gif)
1 /************************************************************** 2 Problem: 1038 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:0 ms 7 Memory:1292 kb 8 ****************************************************************/ 9 10 //BZOJ 1038 11 #include<cmath> 12 #include<vector> 13 #include<cstdio> 14 #include<cstring> 15 #include<cstdlib> 16 #include<iostream> 17 #include<algorithm> 18 #define rep(i,n) for(int i=0;i<n;++i) 19 #define F(i,j,n) for(int i=j;i<=n;++i) 20 #define D(i,j,n) for(int i=j;i>=n;--i) 21 #define pb push_back 22 using namespace std; 23 inline int getint(){ 24 int v=0,sign=1; char ch=getchar(); 25 while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();} 26 while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();} 27 return v*sign; 28 } 29 const int N=310,INF=~0u>>2; 30 typedef long long LL; 31 typedef double lf; 32 const lf eps=1e-8; 33 /******************tamplate*********************/ 34 struct Point{ 35 lf x,y; 36 void read(){scanf("%lf%lf",&x,&y);} 37 }p[N]; 38 struct Line{double k,b;}l[N],st[N]; 39 Line make_line(Point a,Point b){ 40 Line tmp; 41 tmp.k=(a.y-b.y)/(a.x-b.x); 42 tmp.b=a.y-tmp.k*a.x; 43 return tmp; 44 } 45 int n,top; 46 inline bool cmp(Line a,Line b){ 47 if (fabs(a.k-b.k)<eps) return a.b<b.b; 48 return a.k<b.k; 49 } 50 double crossx(Line x1,Line x2){ 51 return (x2.b-x1.b)/(x1.k-x2.k); 52 } 53 void insert(Line a){ 54 while(top){ 55 if (fabs(st[top].k-a.k)<eps) top--; 56 else if (top>1 && crossx(a,st[top-1])<= 57 crossx(st[top],st[top-1])) top--; 58 else break; 59 } 60 st[++top]=a; 61 } 62 lf Up(lf x){ 63 lf ans=0.0; 64 F(i,1,top) 65 ans=max(ans,st[i].k*x+st[i].b); 66 return ans; 67 } 68 lf Down(lf x){ 69 int pos; 70 for(pos=1;pos<n && p[pos+1].x<x;pos++); 71 if (pos==n) return -1e10; 72 Line tmp=make_line(p[pos],p[pos+1]); 73 return tmp.k*x+tmp.b; 74 } 75 76 int main(){ 77 #ifndef ONLINE_JUDGE 78 freopen("1038.in","r",stdin); 79 freopen("1038.out","w",stdout); 80 #endif 81 n=getint(); 82 F(i,1,n) scanf("%lf",&p[i].x); 83 F(i,1,n) scanf("%lf",&p[i].y); 84 F(i,1,n-1) l[i]=make_line(p[i+1],p[i]); 85 sort(l+1,l+n,cmp); 86 F(i,1,n-1) insert(l[i]); 87 lf ans=1e10; 88 F(i,1,n) ans=min(ans,Up(p[i].x)-p[i].y); 89 F(i,2,top){ 90 Point p; 91 p.x=crossx(st[i-1],st[i]); 92 p.y=st[i].k*p.x+st[i].b; 93 ans=min(ans,p.y-Down(p.x)); 94 } 95 printf("%.3lf\n",ans); 96 return 0; 97 }
View Code
1038: [ZJOI2008]瞭望塔
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 1043 Solved: 470
[Submit][Status][Discuss]
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
对于100%的数据, N ≤ 300,输入坐标绝对值不超过106,注意考虑实数误差带来的问题。
Source
[Submit][Status][Discuss]
转载于:https://www.cnblogs.com/Tunix/p/4426259.html
【BZOJ】【1038】【ZJOI2008】瞭望塔相关推荐
- bzoj 1038 [ZJOI2008]瞭望塔
1038: [ZJOI2008]瞭望塔 Time Limit: 10 Sec Memory Limit: 162 MB Submit: 2438 Solved: 1004 [Submit][Sta ...
- BZOJ 1038: [ZJOI2008]瞭望塔 半平面交
Description 致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安.我们 将H村抽象为一维的轮廓.如下图所示 我们可以用一条山的上方轮廓折线(x1 ...
- HYSBZ/BZOJ 1038 [ZJOI2008] 瞭望塔 - 计算几何
题目描述 分析: 题目中说的"可以看见"means 在折线的每段所在直线朝x轴正方向,直线的左边一片区域(其实就是折线的每段所在直线的上面) 所以我们要求的就是此题折线所在直线相交 ...
- BZOJ 1038: [ZJOI2008]瞭望塔
半平面交后,可能成为答案的点就是凸包上的点 和 山峰(分段函数的分段点). 枚举一下就行了. #include <bits/stdc++.h> using namespace std; c ...
- 【BZOJ 1038】 1038: [ZJOI2008]瞭望塔
1038: [ZJOI2008]瞭望塔 Description 致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安.我们 将H村抽象为一维的轮廓.如下图所 ...
- 【BZOJ 1038】 [ZJOI2008]瞭望塔
1038: [ZJOI2008]瞭望塔 Time Limit: 10 Sec Memory Limit: 162 MB Submit: 973 Solved: 428 [ Submit][ S ...
- bzoj千题计划126:bzoj1038: [ZJOI2008]瞭望塔
http://www.lydsy.com/JudgeOnline/problem.php?id=1038 本题可以使用三分法 将点按横坐标排好序后 对于任意相邻两个点连成的线段,瞭望塔的高度 是单峰函 ...
- bzoj1038 [ZJOI2008]瞭望塔(半平面交)
bzoj1038 [ZJOI2008]瞭望塔 原题地址:http://www.lydsy.com/JudgeOnline/problem.php?id=1038 题意: 村中要建立一个瞭望塔,我们将H ...
- luogu P2600 [ZJOI2008]瞭望塔
luogu P2600 [ZJOI2008]瞭望塔 大意 题目讲得很清楚啊 题解 可以发现,那个点一定是某两条直线的交点 然后直接枚举两条直线就好了 // luogu-judger-enable-o2 ...
- 【BZOJ 1038】[ZJOI2008]瞭望塔
[题目链接]:http://www.lydsy.com/JudgeOnline/problem.php?id=1038 [题意] [题解] 可以看到所有村子的瞭望塔所在的位置只会是在相邻两个村子所代表 ...
最新文章
- JavaScript类——鼠标点击下笑脸变化
- yield %%% generator
- 小程序子组件向父组件传值_一套组件化、可复用、易扩展的微信小程序 UI 组件库...
- 浅谈.Net异步编程的前世今生----EAP篇
- nginx 电子书_Nginx最详细的反向代理配置步骤,拿去不谢
- 一个路由器两个网段互通_如何判断两个IP地址是否在同一个网段?什么是子网掩码?...
- python中post请求太慢_AJAX post请求每秒钟慢一次[Django]
- java基础覆盖——知识库搭建-1
- 退出整个Android程序的工具类
- 学python能赚钱吗-哪种Python程序员最赚钱?爬虫数据告诉你!
- 安装ssd后不识别网卡_群晖E10M20-T1:你以为它是张网卡,其实它还带俩SSD
- 使用colab训练faster-rcnn
- 一起欣赏:50+ 极具创意的个人简历设计【下篇】
- [LOL自走棋] 种族职业数据
- ios 获取沙盒文件名_iOS之沙盒路径
- pikachu File Inclusion 文件包含漏洞 (皮卡丘漏洞平台通关系列)
- python批量修改替换文件内容
- air游戏接入小米支付sdk
- Intellij IDEA - Did you kown...?
- 卸载wps后桌面上的office文件图标变成了白色(亲测有效)
热门文章
- 【ARM】数据操作指令(下)
- 【Ubuntu】 使用Xshell5连接Ubuntu16.04
- 广东省计算机大赛设计什么时候,2017年广东省大学生计算机设计大赛
- 每天一道LeetCode-----判断给定字符串是否符合某个模式
- Spark(5)——standalone模式
- 鸿蒙系统执行效率,华为鸿蒙手机优势:兼容所有安卓软件、比安卓运行速度快60%...
- mysql 查询指定字段数据_MySQL使用select语句查询指定表中指定列(字段)的数据
- Linux环境下静态库的生成和使用 (.a文件)
- VMware虚拟机NAT模式网络配置图文教程
- 为了在 Windows 上安装 GCC