题目描述

致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安。

我们将H村抽象为一维的轮廓。如下图所示

我们可以用一条山的上方轮廓折线(x1, y1), (x2, y2), …. (xn, yn)来描述H村的形状,这里x1 < x2 < …< xn。瞭望塔可以建造在[x1, xn]间的任意位置, 但必须满足从瞭望塔的顶端可以看到H村的任意位置。可见在不同的位置建造瞭望塔,所需要建造的高度是不同的。为了节省开支,dadzhi村长希望建造的塔高度尽可能小。

请你写一个程序,帮助dadzhi村长计算塔的最小高度。

输入输出格式

输入格式:

输入文件tower.in第一行包含一个整数n,表示轮廓折线的节点数目。接下来第一行n个整数, 为x1 ~ xn. 第三行n个整数,为y1 ~ yn。

输出格式:

输出文件tower.out仅包含一个实数,为塔的最小高度,精确到小数点后三位。

输入输出样例

输入样例#1: 复制

6
1 2 4 5 6 7
1 2 2 4 2 1
输出样例#1: 复制

1.000

说明

对于60%的数据, N ≤ 60;

对于100%的数据, N ≤ 300,输入坐标绝对值不超过106,注意考虑实数误差带来的问题

这题分两步。第一步就是求出满足条件的半平面,这半部分就是"水平可见直线"那题。

第二部就是计算答案。可以证明瞭望塔的横坐标一定在半平面或地面的拐点处,因为中间部分一定没有其中一端优秀。

所以对半平面和地面的拐点分别拎出来讨论一下就好了。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
struct Line
{
double k,b;
}line[],sta[];
int n,top;
double x[],y[],inf=1e8,eps=1e-,ans=2e12;
int dcmp(double X)
{
if (X>eps) return ;
if (X<-eps) return -;
return ;
}
double getx(Line a,Line b)
{
return ((b.b-a.b)/(a.k-b.k));
}
double gety(double X)
{int i;
for (i=;i<=n;i++)
{
if (x[i+]>=X) break;
}
if (i==n+) return -inf;
double k=(y[i+]-y[i])/(x[i+]-x[i]),b=y[i]-k*x[i];
return X*k+b;
}
bool cmp(Line a,Line b)
{
if (dcmp(a.k-b.k)==)
return a.b<b.b;
return a.k<b.k;
}
int main()
{
int i,j;
double maxx;
cin>>n;
for (i=;i<=n;i++)
scanf("%lf",&x[i]);
for (i=;i<=n;i++)
scanf("%lf",&y[i]);
for (i=;i<=n-;i++)
{
line[i].k=(y[i+]-y[i])/(x[i+]-x[i]);
line[i].b=y[i]-line[i].k*x[i];
}
n--;
sort(line+,line+n+,cmp);
line[n+].k=inf;
sta[]=line[];sta[]=line[];
top=;
for (i=;i<=n;i++)
{
if (dcmp(line[i].k-line[i+].k)==)
continue;
while (top>&&getx(line[i],sta[top-])<=getx(sta[top],sta[top-])) top--;
top++;
sta[top]=line[i];
}
for (i=;i<top;i++)
{
double X=getx(sta[i],sta[i+]);
double Y=sta[i].k*X+sta[i].b;
if (dcmp(Y-gety(X))>=)
ans=min(ans,Y-gety(X));
}
for (i=;i<=n+;i++)
{
maxx=;
for (j=;j<=top;j++)
{
maxx=max(maxx,x[i]*sta[j].k+sta[j].b);
}
if (dcmp(maxx-y[i])>=)
ans=min(ans,maxx-y[i]);
}
printf("%.3lf\n",ans);
}

本题可以使用三分法

将点按横坐标排好序后

对于任意相意两个点连成的线段,瞭望塔的高度 是单峰函数,而且是下凸函数

感性理解单峰就是

瞭望塔建的靠左,为了能看到右边的,要高一点

瞭望塔建的靠右,为了能看到左边的,要高一点

所以 枚举所有线段,三分线段上建造瞭望塔的位置,所有线段上的瞭望塔高度取最小

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
struct Node
{
double k,b;
int pd;
}L[];
int n;
double px[],py[],eps=1e-,ans;
int dcmp(double x)
{
if (x>eps) return ;
if (x<-eps) return -;
return ;
}
double cal(double X,double Y)
{int i;
double tmp=;
for (i=;i<n;i++)
{
if (L[i].pd==) continue;
tmp=max(tmp,L[i].k*X+L[i].b-Y);
}
return tmp;
}
int main()
{int i;
cin>>n;
for (i=;i<=n;i++)
scanf("%lf",&px[i]);
for (i=;i<=n;i++)
scanf("%lf",&py[i]);
for (i=;i<n;i++)
{
if (dcmp(px[i]-px[i+])==) continue;
L[i].k=(py[i]-py[i+])/(px[i]-px[i+]);
L[i].b=py[i]-L[i].k*px[i];
L[i].pd=;
}
ans=2e15;
for (i=;i<n;i++)
{
if (L[i].pd==) continue;
int T=;
double l=px[i],r=px[i+];
double mid1,mid2;
while (T--)
{
mid1=(r-l)/+l,mid2=r-(r-l)/;
if (dcmp(cal(mid1,mid1*L[i].k+L[i].b)-cal(mid2,mid2*L[i].k+L[i].b))>=) l=mid1;
else r=mid2;
}
ans=min(ans,cal(mid1,mid1*L[i].k+L[i].b));
}
printf("%.3lf\n",ans);
}

[ZJOI2008]瞭望塔的更多相关文章

  1. 【BZOJ 1038】 1038: [ZJOI2008]瞭望塔

    1038: [ZJOI2008]瞭望塔 Description 致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安.我们将H村抽象为一维的轮廓.如下图所示 ...

  2. bzoj千题计划126:bzoj1038: [ZJOI2008]瞭望塔

    http://www.lydsy.com/JudgeOnline/problem.php?id=1038 本题可以使用三分法 将点按横坐标排好序后 对于任意相邻两个点连成的线段,瞭望塔的高度 是单峰函 ...

  3. [BZOJ1038][ZJOI2008]瞭望塔(半平面交)

    1038: [ZJOI2008]瞭望塔 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2999  Solved: 1227[Submit][Statu ...

  4. 【BZOJ1038】[ZJOI2008]瞭望塔 半平面交

    [BZOJ1038][ZJOI2008]瞭望塔 Description 致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安.我们将H村抽象为一维的轮廓.如 ...

  5. 1038: [ZJOI2008]瞭望塔

    半平面交. 半平面指的就是一条直线的左面(也不知道对不对) 半平面交就是指很多半平面的公共部分. 这道题的解一定在各条直线的半平面交中. 而且瞭望塔只可能在各个点或者半平面交折线的拐点处. 求出半平面 ...

  6. 1038: [ZJOI2008]瞭望塔 - BZOJ

    Description 致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安.我们将H村抽象为一维的轮廓.如下图所示 我们可以用一条山的上方轮廓折线(x1, ...

  7. bzoj1038: [ZJOI2008]瞭望塔

    Description 致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安.我们将H村抽象为一维的轮廓.如下图所示 我们可以用一条山的上方轮廓折线(x1, ...

  8. 【BZOJ 1038】[ZJOI2008]瞭望塔

    [题目链接]:http://www.lydsy.com/JudgeOnline/problem.php?id=1038 [题意] [题解] 可以看到所有村子的瞭望塔所在的位置只会是在相邻两个村子所代表 ...

  9. [日常摸鱼]bzoj1038 [ZJOI2008]瞭望塔-模拟退火/几何

    题意:给一条平面内$n$个点的折线,要求在折线上搞一个高度$h$的瞭望塔,能够看见折线上所有的点,求$h$的最小值($n \leq 300$) updata2018.1.21 正解半平面交在另一篇里面 ...

随机推荐

  1. JDK1.8源码(六)——java.util.LinkedList 类

    上一篇博客我们介绍了List集合的一种典型实现 ArrayList,我们知道 ArrayList 是由数组构成的,本篇博客我们介绍 List 集合的另一种典型实现 LinkedList,这是一个有链表 ...

  2. 每日冲刺报告——Day5(Java-Team)

    第五天报告(11.6  周一) 团队:Java-Team 成员: 章辉宇(284) 吴政楠(286) 陈阳(PM:288) 韩华颂(142) 胡志权(143) github地址:https://git ...

  3. 项目Alpha冲刺Day4

    一.会议照片 二.项目进展 1.今日安排 学习熟悉前台框架且搭建前台页面框架. 2.问题困难 使用了前端的构建工具webpack,困难在于怎么使用gradle结合它连同后台框架中的配置一起打包,因为本 ...

  4. 设计模式NO.3

    设计模式NO.3 本次博客内容为第三次设计模式的练习.根据老师的要求完成下列题目: 题目1 某商品管理系统的商品名称存储在一个字符串数组中,现需要自定义一个双向迭代器(MyIterator)实现对该商 ...

  5. C语言——第三次作业

    题目1.A乘以B 1.实验代码 #include <stdio.h> int main() { int A,B,C; scanf("%d %d",&A,& ...

  6. android使用sharesdk的小感

    1.sharesdk快捷方式,快捷方式集成了所有需要分享到的手机app,但是具有缺陷,举个例子(想要微信分享图片url,但是短信并不想带有图片,否则短信成彩信,这里集成的就有麻烦了,为了解决这种问题, ...

  7. hdu 5274 Dylans loves tree

    Dylans loves tree http://acm.hdu.edu.cn/showproblem.php?pid=5274 Time Limit: 2000/1000 MS (Java/Othe ...

  8. ASP.NET MVC编程——单元测试

    1自动化测试基本概念 自动化测试分为:单元测试,集成测试,验收测试. 单元测试 检验被测单元的功能,被测单元一般为低级别的组件,如一个类或类方法. 单元测试要满足四个条件:自治的,可重复的,独立的,快 ...

  9. 剑指offer-反转单词顺序列

    题目描述 牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上.同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思.例如,"st ...

  10. os.getcwd()、sys.path[0]、sys.argv[0]和__file__的区别,终于弄清楚了

    os.getcwd().sys.path[0].sys.argv[0]和__file__的区别 要分清这几个的区别与使用条件,实际测试一下是最准确的. 设计测试方法: 一个主模块用来运行,一个子模块用 ...