bzoj 1038: [ZJOI2008]瞭望塔

题意大概就是在村子(山)轮廓之上建一个多么高的塔,可以看到村子全部的点。(一开始怎么也看不懂题意2333)

显然,相邻两点连线,然后所有线交出的区域就是塔建造的可行范围,所以就可以半平面交了233。

答案最小,,,就在分段函数的分段端点处取???(雾,画个图能看出来)

如此神的题%%hzwer

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cmath>
 4 #define eps 1e-8
 5 using namespace std;
 6 double ans=1e60;
 7 int n,cnt,top,tot;
 8 struct point{double x,y;}p[1005],a[1005];
 9 struct line{point a,b; double angle;} l[1005],q[1005];
10 point operator - (point a, point b){
11     point t; t.x=a.x-b.x; t.y=a.y-b.y; return t;
12 }
13 double operator * (point a, point b){
14     return a.x*b.y-a.y*b.x;
15 }
16 bool operator < (line a, line b){
17     if (a.angle==b.angle) return (a.b-a.a)*(b.b-a.a)>0;
18     return a.angle<b.angle;
19 }
20 point intersection(line a, line b)
21 {
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 p=intersection(a,b);
34     return (t.b-t.a)*(p-t.a)<0;
35 }
36 void half_plane_intersection()
37 {
38     int L=1,R=0; tot=0;
39     for (int i=1; i<=cnt; i++)
40     {
41         if (l[i].angle!=l[i-1].angle) tot++;
42         l[tot]=l[i];
43     }
44     cnt=tot;
45     q[++R]=l[1]; q[++R]=l[2];
46     for (int i=3; i<=cnt; i++)
47     {
48         while (L<R && jud(q[R-1],q[R],l[i])) R--;
49         while (L<R && jud(q[L+1],q[L],l[i])) L++;
50         q[++R]=l[i]; 
51     }
52     while (L<R && jud(q[R-1],q[R],q[L])) R--;
53     while (L<R && jud(q[L+1],q[L],q[R])) L++;
54     tot=0;
55     for (int i=L; i<R; i++)
56         a[++tot]=intersection(q[i],q[i+1]);
57 }
58 void pre()
59 {
60     p[0].x=p[1].x; p[0].y=100001;
61     p[n+1].x=p[n].x; p[n+1].y=100001;
62     for (int i=1; i<=n; i++)
63     {
64         l[++cnt].a=p[i-1]; l[cnt].b=p[i];
65         l[++cnt].a=p[i]; l[cnt].b=p[i+1];
66     }
67     for (int i=1; i<=cnt; i++)
68         l[i].angle=atan2(l[i].b.y-l[i].a.y,l[i].b.x-l[i].a.x);
69     sort(l+1,l+cnt+1);
70 }
71 void get_ans()
72 {
73     for (int k=1; k<=tot; k++)
74         for (int i=1; i<n; i++)
75         {
76             point t; t.x=a[k].x; t.y=-1;
77             if (a[k].x>=p[i].x && a[k].x<=p[i+1].x)
78                 ans=min(ans,a[k].y-intersection((line){p[i],p[i+1]},(line){t,a[k]}).y);
79         }
80     for (int k=1; k<=n; k++)
81         for (int i=1; i<tot; i++)
82         {
83             point t; t.x=p[k].x; t.y=-1;
84             if (p[k].x>=a[i].x && p[k].x<=a[i+1].x)
85                 ans=min(ans,intersection((line){a[i],a[i+1]},(line){t,p[k]}).y-p[k].y);
86         }
87         
88 }
89 int main()
90 {
91     scanf("%d",&n);
92     for (int i=1; i<=n; i++) scanf("%lf",&p[i].x);
93     for (int i=1; i<=n; i++) scanf("%lf",&p[i].y);
94     pre();
95     half_plane_intersection();
96     get_ans();
97     printf("%.3lf",ans);
98     return 0;
99 }

 

posted @ 2017-03-02 07:31  ws_ccd  阅读(197)  评论(0编辑  收藏  举报