• bzoj 1038 [ZJOI2008]瞭望塔(半平面交)


    【题目链接】

        http://www.lydsy.com/JudgeOnline/problem.php?id=1038

    【题意】

        找一个最低塔高使可以看到村庄的每一个角落。

    【思路】

       

        半平面交

        能够看到一个线段的点都在该线段所在直线的上方,如果能看到所有的线段则该区域就是所有线段所在直线的半平面交。

        最低塔高就是要求这个区域与村庄之间的最短距离。无论是交还是村庄都可以看作是分段的一次函数,所以最近距离一定在分段点处取得。分别枚举交和村庄的分段点即可。

        需要注意的有:预先添加两个边界。求最近距离时先判断一下x的关系,否则谁知道交点飞到哪去T_T

    【代码】

      1 #include<cmath>
      2 #include<cstdio>
      3 #include<vector>
      4 #include<cstring>
      5 #include<iostream>
      6 #include<algorithm>
      7 using namespace std;
      8 
      9 const int N =  305;
     10 const double bond = 100001;
     11 const double eps = 1e-10;
     12 
     13 struct Pt {
     14     double x,y;
     15     Pt (double x=0,double y=0):x(x),y(y){}
     16 };
     17 typedef Pt vec;
     18 
     19 vec operator + (Pt a,Pt b) { return vec(a.x+b.x,a.y+b.y); }
     20 vec operator - (Pt a,Pt b) { return vec(a.x-b.x,a.y-b.y); }
     21 vec operator * (Pt a,double p) { return vec(a.x*p,a.y*p); }
     22 
     23 double cross(Pt a,Pt b) { return a.x*b.y-a.y*b.x; }
     24 
     25 struct Line {
     26     Pt p; vec v; double ang;
     27     Line () {}
     28     Line (Pt p,vec v) :p(p),v(v){ ang=atan2(v.y,v.x); }
     29     bool operator < (const Line& rhs) const {
     30         return ang<rhs.ang;
     31     }
     32 };
     33 
     34 bool onleft(Line L,Pt p) { return cross(L.v,p-L.p)>0; }
     35 Pt LineInter(Line a,Line b) 
     36 {
     37     vec u=a.p-b.p;
     38     double t=cross(b.v,u)/cross(a.v,b.v);
     39     return a.p+a.v*t;
     40 }
     41 vector<Pt> HPI(vector<Line> L)
     42 {
     43     int n=L.size();
     44     sort(L.begin(),L.end());
     45     int f,r;
     46     vector<Pt> p(n) , ans;
     47     vector<Line> q(n);
     48     q[f=r=0]=L[0];
     49     for(int i=1;i<n;i++) {
     50         while(f<r&&!onleft(L[i],p[r-1])) r--;
     51         while(f<r&&!onleft(L[i],p[f])) f++;
     52         q[++r]=L[i];
     53         if(fabs(cross(q[r].v,q[r-1].v))<eps) {
     54             r--;
     55             if(onleft(q[r],L[i].p)) q[r]=L[i];
     56         }
     57         if(f<r) p[r-1]=LineInter(q[r-1],q[r]);
     58     }
     59     while(f<r&&!onleft(q[f],p[r-1])) r--;
     60     if(r-f<=1) return ans;
     61     p[r]=LineInter(q[r],q[f]);
     62     for(int i=f;i<=r;i++) ans.push_back(p[i]);
     63     return ans; 
     64 }
     65 
     66 vector<Line> L;
     67 vector<Pt> p,np;
     68 int n;
     69 
     70 int main()
     71 {
     72     scanf("%d",&n);
     73     double x[N],y[N];
     74     for(int i=1;i<=n;i++) {
     75         scanf("%lf",&x[i]);
     76     }
     77     for(int i=1;i<=n;i++) {
     78         scanf("%lf",&y[i]);
     79     }
     80     p.push_back(Pt(x[1],y[1]+1));
     81     for(int i=1;i<=n;i++) p.push_back(Pt(x[i],y[i]));
     82     p.push_back(Pt(x[n],y[n]+1));
     83     for(int i=0;i<=n;i++) {
     84         L.push_back(Line(p[i],p[i+1]-p[i]));
     85     }
     86     np=HPI(L);
     87     double ans=1e30;
     88     for(int i=0;i<np.size();i++)
     89         for(int j=1;j<=n;j++) if(np[i].x>=p[j].x&&np[i].x<=p[j+1].x)  {
     90             Pt x=Pt(np[i].x,-1);
     91             x=LineInter(Line(p[j],p[j+1]-p[j]),Line(x,np[i]-x));
     92             ans=min(ans,np[i].y-x.y);
     93         }
     94     for(int i=1;i<=n;i++)
     95         for(int j=0;j<(int)np.size()-1;j++) if(p[i].x>=np[j].x&&p[i].x<=np[j+1].x)  {
     96             Pt x=Pt(p[i].x,-1);
     97             x=LineInter(Line(np[j],np[j+1]-np[j]),Line(x,p[i]-x));
     98             ans=min(ans,x.y-p[i].y);
     99         }
    100     printf("%.3lf",ans);
    101     return 0;
    102 }
  • 相关阅读:
    奇技淫巧训练之一
    基于JS模块化现状谈谈选择ES6模块的原因
    vue-cli3项目搭建配置以及性能优化
    Umi + DvaJS
    ReactFragment用法介绍
    什么是纯函数
    10.25考试
    10.23考试
    线段树合并(雨天的尾巴 题解)
    10.21考试
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5266119.html
Copyright © 2020-2023  润新知