BZOJ 1038 瞭望塔
Description
致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安。我们将H村抽象为一维的轮廓。如下图所示 我们可以用一条山的上方轮廓折线(x1, y1), (x2, y2), …. (xn, yn)来描述H村的形状,这里x1 < x2 < …< xn。瞭望塔可以建造在[x1, xn]间的任意位置, 但必须满足从瞭望塔的顶端可以看到H村的任意位置。可见在不同的位置建造瞭望塔,所需要建造的高度是不同的。为了节省开支,dadzhi村长希望建造的塔高度尽可能小。请你写一个程序,帮助dadzhi村长计算塔的最小高度。
Input
第一行包含一个整数n,表示轮廓折线的节点数目。接下来第一行n个整数, 为x1 ~ xn. 第三行n个整数,为y1 ~ yn。
Output
仅包含一个实数,为塔的最小高度,精确到小数点后三位。
Sample Input
【输入样例一】
6
1 2 4 5 6 7
1 2 2 4 2 1
【输入样例二】
4
10 20 49 59
0 10 10 0
6
1 2 4 5 6 7
1 2 2 4 2 1
【输入样例二】
4
10 20 49 59
0 10 10 0
Sample Output
【输出样例一】
1.000
【输出样例二】
14.500
1.000
【输出样例二】
14.500
HINT
对于100%的数据, N ≤ 300,输入坐标绝对值不超过106,注意考虑实数误差带来的问题。
Source
半平面交。对于每条线段,所能看到其整条线段的点一定的在其所延长直线的上方,因此我们可以对所以直线求一次半平面交。
然后,最优解一定在线段端点处或半平面交所得多边形的顶点处。
1 #include<iostream> 2 #include<algorithm> 3 #include<cmath> 4 #include<cstdio> 5 #include<cstdlib> 6 #include<cstring> 7 using namespace std; 8 9 #define eps (1e-6) 10 #define oo ((double)(1ll<<50)) 11 #define maxn 310 12 int n,m,tot,cnt; 13 double ans = oo; 14 struct NODE 15 { 16 double x,y; 17 friend inline NODE operator + (const NODE &p,const NODE &q) { return (NODE) {p.x+q.x,p.y+q.y}; } 18 friend inline NODE operator - (const NODE &p,const NODE &q) { return (NODE) {p.x-q.x,p.y-q.y}; } 19 friend inline NODE operator * (const NODE &p,const double &q) { return (NODE) {p.x*q,p.y*q}; } 20 friend inline double operator /(const NODE &p,const NODE &q) { return p.x*q.y-p.y*q.x; } 21 inline double alpha() { return atan2(y,x); } 22 }mou[maxn],pol[maxn],pp[maxn]; 23 struct LINE 24 { 25 NODE p,v; double slop; 26 inline void maintain() { slop = v.alpha(); } 27 friend inline bool operator <(const LINE &l1,const LINE &l2) { return l1.slop < l2.slop; } 28 }lines[maxn],qq[maxn]; 29 struct SCAN 30 { 31 double x,y; int id; bool sign; 32 friend inline bool operator <(const SCAN &a,const SCAN &b) 33 { 34 if (a.x != b.x) return a.x < b.x; 35 else return a.sign < b.sign; 36 } 37 }bac[maxn]; 38 39 inline bool ol(const LINE &l,const NODE &p) { return l.v/(p-l.p) > 0; } 40 41 inline NODE cp(const LINE &a,const LINE &b) 42 { 43 NODE u = a.p - b.p; 44 double t = (b.v/u)/(a.v/b.v); 45 return a.p+a.v*t; 46 } 47 48 inline bool para(const LINE &a,const LINE &b) 49 { 50 return fabs(a.v/b.v) < eps; 51 } 52 53 inline void ready() 54 { 55 for (int i = 1;i < n;++i) 56 { 57 lines[++tot] = (LINE) {mou[i],(mou[i+1]-mou[i])*1e-3}; 58 lines[tot].maintain(); 59 } 60 lines[++tot] = (LINE) {(NODE) {-oo,0},(NODE){0,-0.001}}; 61 lines[tot].maintain(); 62 63 lines[++tot] = (LINE) {(NODE) {0,oo},(NODE){-0.001,0}}; 64 lines[tot].maintain(); 65 66 lines[++tot] = (LINE) {(NODE) {oo,0},(NODE){0,0.001}}; 67 lines[tot].maintain(); 68 69 lines[++tot] = (LINE) {(NODE) {0,-oo},(NODE){0.001,0}}; 70 lines[tot].maintain(); 71 } 72 73 inline int half_plane_intersection() 74 { 75 sort(lines+1,lines+tot+1); 76 int head,tail; 77 qq[head = tail = 1] = lines[1]; 78 for (int i = 2;i <= tot;++i) 79 { 80 while (head < tail&&!ol(lines[i],pp[tail-1])) --tail; 81 while (head < tail&&!ol(lines[i],pp[head])) ++head; 82 qq[++tail] = lines[i]; 83 if (para(qq[tail],qq[tail-1])) 84 { 85 tail--; 86 if (ol(qq[tail],lines[i].p)) qq[tail] = lines[i]; 87 } 88 if (head < tail) pp[tail-1] = cp(qq[tail],qq[tail-1]); 89 } 90 while (head < tail && !ol(qq[head],pp[tail-1])) --tail; 91 if (tail-head <= 0) return 0; 92 pp[tail] = cp(qq[tail],qq[head]); 93 for (int i = head;i <= tail;++i) pol[++m] = pp[i]; 94 pol[0] = pol[m]; 95 return m; 96 } 97 98 inline void work() 99 { 100 int all = 0; 101 for (int i = 1;i <= n;++i) 102 bac[++all] = (SCAN) { mou[i].x,mou[i].y,i,false }; 103 for (int i = 1;i <= m;++i) 104 if (pol[i].x >= mou[1].x&&pol[i].x <= mou[n].x) 105 bac[++all] = (SCAN) { pol[i].x,pol[i].y,i,true }; 106 sort(bac+1,bac+all+1); 107 int s1,s2; 108 for (int i = 1;i <= all;++i) if (bac[i].sign) { s1 = bac[i].id-1; break; } 109 for (int i = 1;i <= all;++i) 110 { 111 LINE l = (LINE) {(NODE) {bac[i].x,0},(NODE) {0,1}},l1; NODE p; 112 if (!bac[i].sign) 113 { 114 l1= (LINE) {pol[s1],pol[s1+1]-pol[s1]}; 115 s2 = bac[i].id; 116 } 117 else 118 { 119 l1= (LINE) {mou[s2],mou[s2+1]-mou[s2]}; 120 s1 = bac[i].id; 121 } 122 p = cp(l,l1); 123 ans = min(ans,fabs(p.y-bac[i].y)); 124 } 125 } 126 127 int main() 128 { 129 freopen("1038.in","r",stdin); 130 freopen("1038.out","w",stdout); 131 scanf("%d ",&n); 132 for (int i = 1;i <= n;++i) scanf("%lf",&mou[i].x); 133 for (int i = 1;i <= n;++i) scanf("%lf",&mou[i].y); 134 ready(); 135 half_plane_intersection(); 136 work(); 137 printf("%.3lf",ans); 138 fclose(stdin); fclose(stdout); 139 return 0; 140 }
高考结束,重新回归。