zoukankan      html  css  js  c++  java
  • [BZOJ1038][ZJOI2008]瞭望塔(半平面交)

    1038: [ZJOI2008]瞭望塔

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 2999  Solved: 1227
    [Submit][Status][Discuss]

    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

    Sample Output

    【输出样例一】
    1.000
    【输出样例二】
    14.500

    HINT

     N ≤ 300,输入坐标绝对值不超过106,注意考虑实数误差带来的问题。

    Source

    [Submit][Status][Discuss]

    这题做的真是。。心力交瘁。。其实就是一个半平面交,然而我发现自己实际上完全不会这个东西。

    据说模拟退火和三分都可以做,但是考虑将每条边的上半部分求交,最后这个凸包上的点和原折线的这点才可能是答案。

    证明应该是分段一次函数的极致只可能出现在端点上。

    剩下的就是一系列半平面交模板的问题了,写了一个先将两点式转成点斜式直线方程再求交的函数,WA,发现点斜式根本不能处理与y轴平行的直线。

    然后又看了以前模板中的定比分点叉积求交的函数,WA,发现这个只能求线段交点。

    https://blog.csdn.net/u013050857/article/details/40923789

    最后极不情愿地写了将式子化到底的做法,感觉这个函数根本背不下来。

    不过幸好发现了这个问题,否则考场上要是写了就会很惨。

     1 #include<cmath>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #define rep(i,l,r) for (int i=l; i<=r; i++)
     5 typedef double db;
     6 using namespace std;
     7 
     8 const int N=1010;
     9 const double eps=1e-8;
    10 int n,tot,cnt;
    11 db ans=1e60;
    12 struct P{ db x,y; }p[N],a[N];
    13 struct L{ P a,b; db sl; }l[N],q[N],tmp[N];
    14 
    15 double dmult(P a,P b,P c){ return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y); }
    16 bool operator <(const L &a,const L &b){ return (a.sl!=b.sl) ? a.sl<b.sl : dmult(a.a,a.b,b.b)<-eps; }
    17 
    18 P inter(L a,L b){
    19     double A1=a.b.y-a.a.y,B1=a.a.x-a.b.x,C1=-B1*a.a.y-A1*a.a.x;
    20     double A2=b.b.y-b.a.y,B2=b.a.x-b.b.x,C2=-B2*b.a.y-A2*b.a.x;
    21     return (P){(C1*B2-C2*B1)/(B1*A2-B2*A1),(C1*A2-C2*A1)/(A1*B2-A2*B1)};
    22 }
    23 bool jud(L a,L b,L c){ P t=inter(a,b); return dmult(c.a,c.b,t)<-eps; }
    24 
    25 void work(){
    26     tmp[++tot]=l[1];
    27     rep(i,2,cnt) if (fabs(l[i].sl-l[i-1].sl)>eps) tmp[++tot]=l[i];
    28     rep(i,1,tot) l[i]=tmp[i];
    29     int L=1,R=0; q[++R]=l[1]; q[++R]=l[2];
    30     rep(i,3,tot){
    31         while (L<R && jud(q[R-1],q[R],l[i])) R--;
    32         while (L<R && jud(q[L+1],q[L],l[i])) L++;
    33         q[++R]=l[i];
    34     }
    35     while (L<R && jud(q[R-1],q[R],q[L])) R--;
    36     while (L<R && jud(q[L+1],q[L],q[R])) L++;
    37     tot=0; rep(i,L,R-1) p[++tot]=inter(q[i],q[i+1]);
    38 }
    39 
    40 void getans(){
    41     rep(k,1,tot)
    42         rep(i,1,n-1){
    43             P t=(P){p[k].x,-1};
    44             if (p[k].x>=a[i].x && p[k].x<=a[i+1].x)
    45                 ans=min(ans,p[k].y-inter((L){a[i],a[i+1]},(L){t,p[k]}).y);
    46         }
    47     rep(k,1,n)
    48         rep(i,1,tot-1){
    49             P t=(P){a[k].x,-1};
    50             if (a[k].x>=p[i].x && a[k].x<=p[i+1].x)
    51                 ans=min(ans,inter((L){p[i],p[i+1]},(L){t,a[k]}).y-a[k].y);
    52         }
    53 }
    54 
    55 int main(){
    56     scanf("%d",&n);
    57     rep(i,1,n) scanf("%lf",&a[i].x);
    58     rep(i,1,n) scanf("%lf",&a[i].y);
    59     a[0]=(P){a[1].x,100000}; a[n+1]=(P){a[n].x,100000};
    60     rep(i,0,n) l[++cnt]=(L){a[i],a[i+1],atan2(a[i+1].y-a[i].y,a[i+1].x-a[i].x)};
    61     sort(l+1,l+cnt+1); work(); getans(); printf("%.3lf
    ",ans);
    62     return 0;
    63 }
    View Code

    UPD:感觉自己十分愚蠢,与y轴平行的直线判一下不就好了。

     1 #include<cmath>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #define rep(i,l,r) for (int i=l; i<=r; i++)
     5 #define A double k2=(b.b.y-b.a.y)/(b.b.x-b.a.x),b2=b.a.y-k2*b.a.x
     6 #define B double k1=(a.b.y-a.a.y)/(a.b.x-a.a.x),b1=a.a.y-k1*a.a.x
     7 typedef double db;
     8 using namespace std;
     9 
    10 const int N=1010;
    11 const double eps=1e-8;
    12 int n,tot,cnt;
    13 db ans=1e60;
    14 struct P{ db x,y; }p[N],a[N];
    15 struct L{ P a,b; db sl; }l[N],q[N],tmp[N];
    16 
    17 double dmult(P a,P b,P c){ return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y); }
    18 bool operator <(const L &a,const L &b){ return (a.sl!=b.sl) ? a.sl<b.sl : dmult(a.a,a.b,b.b)<-eps; }
    19 
    20 P inter(L a,L b){
    21     if (a.a.x==a.b.x){ A; return (P){a.a.x,k2*a.a.x+b2}; }
    22     if (b.a.x==b.b.x){ B; return (P){b.a.x,k1*b.a.x+b1}; }
    23     A; B; double x=(b2-b1)/(k1-k2),y=k1*x+b1;
    24     return (P){x,y};
    25 }
    26 
    27 bool jud(L a,L b,L c){ P t=inter(a,b); return dmult(c.a,c.b,t)<-eps; }
    28 
    29 void work(){
    30     tmp[++tot]=l[1];
    31     rep(i,2,cnt) if (fabs(l[i].sl-l[i-1].sl)>eps) tmp[++tot]=l[i];
    32     rep(i,1,tot) l[i]=tmp[i];
    33     int L=1,R=0; q[++R]=l[1]; q[++R]=l[2];
    34     rep(i,3,tot){
    35         while (L<R && jud(q[R-1],q[R],l[i])) R--;
    36         while (L<R && jud(q[L+1],q[L],l[i])) L++;
    37         q[++R]=l[i];
    38     }
    39     while (L<R && jud(q[R-1],q[R],q[L])) R--;
    40     while (L<R && jud(q[L+1],q[L],q[R])) L++;
    41     tot=0; rep(i,L,R-1) p[++tot]=inter(q[i],q[i+1]);
    42 }
    43 
    44 void getans(){
    45     rep(k,1,tot)
    46         rep(i,1,n-1){
    47             P t=(P){p[k].x,-1};
    48             if (p[k].x>=a[i].x && p[k].x<=a[i+1].x)
    49                 ans=min(ans,p[k].y-inter((L){a[i],a[i+1]},(L){t,p[k]}).y);
    50         }
    51     rep(k,1,n)
    52         rep(i,1,tot-1){
    53             P t=(P){a[k].x,-1};
    54             if (a[k].x>=p[i].x && a[k].x<=p[i+1].x)
    55                 ans=min(ans,inter((L){p[i],p[i+1]},(L){t,a[k]}).y-a[k].y);
    56         }
    57 }
    58 
    59 int main(){
    60     freopen("tower.in","r",stdin);
    61     freopen("tower.out","w",stdout);
    62     scanf("%d",&n);
    63     rep(i,1,n) scanf("%lf",&a[i].x);
    64     rep(i,1,n) scanf("%lf",&a[i].y);
    65     a[0]=(P){a[1].x,100000}; a[n+1]=(P){a[n].x,100000};
    66     rep(i,0,n) l[++cnt]=(L){a[i],a[i+1],atan2(a[i+1].y-a[i].y,a[i+1].x-a[i].x)};
    67     sort(l+1,l+cnt+1); work(); getans(); printf("%.3lf
    ",ans);
    68     return 0;
    69 }
    View Code
  • 相关阅读:
    python多线程多进程
    python单元测试unittest
    python学习笔记(一):python简介和入门
    今天的收获!!!
    Python django
    React router
    30分钟掌握ES6/ES2015核心内容
    webpack+React.js
    我喜欢的两个js类实现方式 现在再加上一个 极简主义法
    js实现的笛卡尔乘积-商品发布
  • 原文地址:https://www.cnblogs.com/HocRiser/p/8974434.html
Copyright © 2011-2022 走看看