BZOJ1038 瞭望塔

Posted 大奕哥&VANE

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }

 

以上是关于BZOJ1038 瞭望塔的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 1038 ZJOI 2008 瞭望塔 半平面交

BZOJ1038ZJOI2008瞭望塔 [模拟退火]

BZOJ1038 瞭望塔

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

BZOJ 1038 ZJOI2008 瞭望塔 半平面交

bzoj1038