【半平面交】bzoj1038 [ZJOI2008]瞭望塔

http://m.blog.csdn.net/blog/qpswwww/44105605

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define EPS 0.0000001
#define N 311
typedef double db;
const db PI=acos(-1.0);
struct Point{db x,y;};
typedef Point Vector;
Vector operator - (const Point &a,const Point &b){return (Vector){a.x-b.x,a.y-b.y};}
Vector operator * (const Vector &a,const db &k){return (Vector){a.x*k,a.y*k};}
Vector operator + (const Vector &a,const Vector &b){return (Vector){a.x+b.x,a.y+b.y};}
db Cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;}
struct Line
{
    Point p; Vector v; db ang;
    Line(){}
    Line(const Point &a,const Point &b)
      {
        v=b-a;
        p=a;
        ang=atan2(v.y,v.x);
        if(ang<0) ang+=2.0*PI;
      }
};
bool operator < (const Line &a,const Line &b){return a.ang<b.ang;}
bool OnLeft(Line l,Point a){return Cross(l.v,a-l.p)>0;}
Point GetJiaodian(Line a,Line b){return a.p+a.v*(Cross(b.v,a.p-b.p)/Cross(a.v,b.v));}
int n;
Point ps[N];
Line q[N];
int head=1,tail=1;
Line ls[N];
void BPMJ()
{
    sort(ls+1,ls+n+1);
    q[1]=ls[1];
    for(int i=2;i<=n;++i)
      {
        while(head<tail&&(!OnLeft(ls[i],ps[tail-1]))) --tail;
        while(head<tail&&(!OnLeft(ls[i],ps[head]))) ++head;
        q[++tail]=ls[i];
        if(fabs(Cross(q[tail].v,q[tail-1].v))<EPS)
          {
            --tail;
            if(OnLeft(q[tail],ls[i].p))
              q[tail]=ls[i];
          }
        if(head<tail)
          ps[tail-1]=GetJiaodian(q[tail-1],q[tail]);
      }
    while(head<tail&&(!OnLeft(q[head],ps[tail-1]))) --tail;
    ps[tail]=GetJiaodian(q[tail],q[head]);
}
int nn;
Point a[N];
db ans=999999999999999999.0;
#define INF 10000000000.0
int main()
{
//  freopen("bzoj1038.in","r",stdin);
    scanf("%d",&nn);
    for(int i=1;i<=nn;++i) scanf("%lf",&a[i].x);
    for(int i=1;i<=nn;++i) scanf("%lf",&a[i].y);
    for(int i=1;i<nn;++i) ls[++n]=Line(a[i],a[i+1]);
    ls[++n]=Line((Point){INF,INF},(Point){-INF,INF});
    ls[++n]=Line((Point){-INF,INF},(Point){-INF,-INF});
    ls[++n]=Line((Point){-INF,-INF},(Point){INF,-INF});
    ls[++n]=Line((Point){INF,-INF},(Point){INF,INF});
    BPMJ();
    for(int i=head;i<=tail;++i)
      for(int j=1;j<nn;++j)
        if(ps[i].x>=a[j].x&&ps[i].x<=a[j+1].x)
          {
            db ty=a[j].y+(ps[i].x-a[j].x)/(a[j+1].x-a[j].x)*(a[j+1].y-a[j].y);
            ans=min(ans,ps[i].y-ty);
            break;
          }
    for(int i=1;i<=nn;++i)
      {
        for(int j=head;j<tail;++j)
          if(a[i].x>=ps[j].x&&a[i].x<=ps[j+1].x)
            {
              db ty=ps[j].y+(a[i].x-ps[j].x)/(ps[j+1].x-ps[j].x)*(ps[j+1].y-ps[j].y);
              ans=min(ans,ty-a[i].y);
            }
        if(a[i].x>=ps[tail].x&&a[i].x<=ps[head].x)
          {
            db ty=ps[tail].y+(a[i].x-ps[tail].x)/(ps[head].x-ps[tail].x)*(ps[head].y-ps[tail].y);
            ans=min(ans,ty-a[i].y);
          }
      }
    printf("%.3lf\n",ans);
    return 0;
}
时间: 2024-10-12 16:28:12

【半平面交】bzoj1038 [ZJOI2008]瞭望塔的相关文章

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

http://www.lydsy.com/JudgeOnline/problem.php?id=1038 本题可以使用三分法 将点按横坐标排好序后 对于任意相邻两个点连成的线段,瞭望塔的高度 是单峰函数,而且是下凸函数 感性理解单峰就是 瞭望塔建的靠左,为了能看到右边的,要高一点 瞭望塔建的靠右,为了能看到左边的,要高一点 所以 枚举所有线段,三分线段上建造瞭望塔的位置,所有线段上的瞭望塔高度取最小 #include<cmath> #include<cstdio> #include

BZOJ-1038 [ZJOI2008]瞭望塔

先求半平面交,然后建塔的地方肯定是在半平面交的交点上或者是在地面线段的交点上. #include <cstdlib> #include <cstdio> #include <cstring> #include <cmath> #include <iostream> #include <algorithm> #include <cctype> #define rep(i, l, r) for(int i=l; i<=r

[日常摸鱼]bzoj1038[ZJOI2008]瞭望塔-半平面交

这回好好用半平面交写一次- 看了cls当年写的代码看了好久大概看懂了-cls太强辣 #include<cstdio> #include<iostream> #include<algorithm> #define rep(i,n) for(register int i=1;i<=n;i++) #define REP(i,a,b) for(register int i=a;i<=b;i++) #define debug(x) cout<<#x<

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

[BZOJ1038][ZJOI2008]瞭望塔 Description 致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安.我们将H村抽象为一维的轮廓.如下图所示 我们可以用一条山的上方轮廓折线(x1, y1), (x2, y2), …. (xn, yn)来描述H村的形状,这里x1 < x2 < …< xn.瞭望塔可以建造在[x1, xn]间的任意位置, 但必须满足从瞭望塔的顶端可以看到H村的任意位置.可见在不同的位置建造瞭望塔,所需要建造的

【BZOJ 1038】 [ZJOI2008]瞭望塔

1038: [ZJOI2008]瞭望塔 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 973  Solved: 428 [Submit][Status] Description 致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安.我们将H村抽象为一维的轮廓.如下图所示 我们可以用一条山的上方轮廓折线(x1, y1), (x2, y2), -. (xn, yn)来描述H村的形状,这里x1 < x2 <

1038: [ZJOI2008]瞭望塔

半平面交. 半平面指的就是一条直线的左面(也不知道对不对) 半平面交就是指很多半平面的公共部分. 这道题的解一定在各条直线的半平面交中. 而且瞭望塔只可能在各个点或者半平面交折线的拐点处. 求出半平面交,枚举即可. #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #define eps 1e-7 using namespace std; const int maxn

BZOJ 1038 ZJOI2008 瞭望塔 模拟退火+二分答案

题目大意:给定一条折线,要求选择一个点建立高度为h的瞭望塔,要求瞭望塔塔顶可以看到折线上的每一个点,求h的最小值 正解:半平面交 不会! 于是我们选择模拟退火来寻找瞭望塔的横坐标 确定瞭望塔的高度的时候我们选择二分处理 对于二分的每一个值 我们把折线上的端点从左到右枚举 瞭望塔的塔尖到每个端点的连线必须从左到右逆时针顺序 否则就会被遮挡 如图,塔尖到点2的连线在到点1的连线的顺时针方向,故点1被遮挡,该高度不可行 写完交上去各种秒WA,最后发现我的INF又不够大...我沙茶,我蒟蒻,我这个不长记

P2600 [ZJOI2008]瞭望塔

题目描述 致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安. 我们将H村抽象为一维的轮廓.如下图所示 我们可以用一条山的上方轮廓折线(x1, y1), (x2, y2), -. (xn, yn)来描述H村的形状,这里x1 < x2 < -< xn.瞭望塔可以建造在[x1, xn]间的任意位置, 但必须满足从瞭望塔的顶端可以看到H村的任意位置.可见在不同的位置建造瞭望塔,所需要建造的高度是不同的.为了节省开支,dadzhi村长希望建造的塔高度

[ZJOI2008]瞭望塔

题目描述 致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安. 我们将H村抽象为一维的轮廓.如下图所示 我们可以用一条山的上方轮廓折线(x1, y1), (x2, y2), …. (xn, yn)来描述H村的形状,这里x1 < x2 < …< xn.瞭望塔可以建造在[x1, xn]间的任意位置, 但必须满足从瞭望塔的顶端可以看到H村的任意位置.可见在不同的位置建造瞭望塔,所需要建造的高度是不同的.为了节省开支,dadzhi村长希望建造的塔高度