zoukankan      html  css  js  c++  java
  • BZOJ1038 瞭望塔

    学习了半平交面。

    我这里写的是训练指南中的双端队列,每次判断是否删去更优然后更新。

    看hzwer中有一处不太明白就是为何要将两段加入队列

    后来对拍出错才知道是因为精度,当两线重合时他们叉积返回值是一个极小值

    所以判断一下精度即可。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=2005;
     4 int n,m,cnt,tot;double ans=1e20,eps=1e-8;
     5 struct point{
     6     double x,y;
     7 }a[N],p[N];
     8 point operator -(point a,point b){
     9     point t;t.x=b.x-a.x;t.y=b.y-a.y;
    10     return t;
    11 }
    12 double operator *(point a,point b){
    13     return a.x*b.y-a.y*b.x;
    14 }
    15 struct line{
    16     point a,b;double slop;
    17     bool operator <(const line &B)const{
    18         return slop==B.slop?(b-a)*(B.b-a)>0:slop<B.slop;
    19     }
    20 }l[N],s[N];
    21 point inter(line a,line b){
    22     double k1,k2,t;
    23     k1=(b.b-a.a)*(a.b-a.a);
    24     k2=(a.b-a.a)*(b.a-a.a);
    25     t=k1/(k1+k2);
    26     point ans;
    27     ans.x=b.b.x+(b.a.x-b.b.x)*t;
    28     ans.y=b.b.y+(b.a.y-b.b.y)*t;
    29     return ans;
    30 }
    31 bool jud(line a,line b,line t)
    32 {
    33     point pp=inter(a,b);
    34     return (t.b-t.a)*(pp-t.a)<-eps;
    35 }
    36 void hpl()
    37 {
    38     int L=1,R=0;
    39     for(int i=1;i<=cnt;++i)
    40     {
    41         if(l[i].slop!=l[i-1].slop)++tot;
    42         l[tot]=l[i];
    43     }
    44     cnt=tot;tot=0;
    45     s[++R]=l[1];s[++R]=l[2];
    46     for(int i=3;i<=cnt;++i)
    47     {
    48         while(L<R&&jud(s[R-1],s[R],l[i]))R--;
    49         while(L<R&&jud(s[L+1],s[L],l[i]))L++;
    50         s[++R]=l[i];
    51     }
    52     while(L<R&&jud(s[R-1],s[R],s[L]))R--;
    53 
    54     while(L<R&&jud(s[L+1],s[L],s[R]))L++;
    55     for(int i=L;i<R;++i)
    56     a[++tot]=inter(s[i],s[i+1]);
    57 }
    58 void getans()
    59 {
    60     for(int i=1;i<=tot;++i)
    61     {
    62         point t;t.x=a[i].x;t.y=-1;
    63         for(int j=1;j<n;++j)
    64         if(p[j].x<=a[i].x&&p[j+1].x>=a[i].x)
    65         ans=min(ans,a[i].y-inter((line){p[j],p[j+1]},(line){t,a[i]}).y);
    66     }
    67     for(int i=1;i<=n;++i)
    68     {
    69         point t;t.x=p[i].x;t.y=-1;
    70         for(int j=1;j<tot;++j)
    71         if(a[j].x<=p[i].x&&a[j+1].x>=p[i].x)
    72         ans=min(ans,inter((line){a[j],a[j+1]},(line){t,p[i]}).y-p[i].y);
    73     }
    74 }
    75 int main()
    76 {
    77 //    freopen("1.out","r",stdin);
    78 //    freopen("my.out","w",stdout);
    79     scanf("%d",&n);
    80     for(int i=1;i<=n;++i)scanf("%lf",&p[i].x);
    81     for(int i=1;i<=n;++i)scanf("%lf",&p[i].y);
    82 //    p[0].x=p[1].x;p[0].y=1e9;
    83 //    p[n+1].x=p[n].x;p[n+1].y=1e9;
    84     for(int i=1;i<n;++i)l[++cnt].a=p[i],l[cnt].b=p[i+1];
    85     if(cnt<3){
    86         puts("0.000");return 0;
    87     }
    88     for(int i=1;i<=cnt;++i)
    89     l[i].slop=atan2(l[i].b.y-l[i].a.y,l[i].b.x-l[i].a.x);
    90     sort(l+1,l+1+cnt);
    91     hpl();
    92     getans();
    93     printf("%.3lf",ans);
    94     return 0;
    95 }
  • 相关阅读:
    09-2:跳台阶
    09:菲波那切数列
    08:旋转数组的最小值
    07:用两个栈实现队列
    06:重建二叉树
    05:从尾到头打印链表
    04:替换字符
    centos7安装Jenkins更改默认端口并配置Ldap服务器进行用户认证
    Jira配置openLdap服务器进行用户认证
    定时自动从FTP服务器取数据脚本
  • 原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8379343.html
Copyright © 2011-2022 走看看