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
  • 相关阅读:
    Asp.net弹出浏览器客户端确认对话框代码 Carlwave
    VS 2005 与SQL Server 2005整合优势在哪里?(from csdn.net) Carlwave
    如何让搜索引擎收录我的站点 Carlwave
    超强扩展性的DNNDotNetNuke模块功能分类列表(from 中国DNN) Carlwave
    DotNetNuke命名空间概述 Carlwave
    Most Popular Questions and Answers on ASP.NET Whidbey(from asp.net forums,write by ASP.NET Team) Carlwave
    火箭官方宣告麦蒂缺阵五周 季后赛前景蒙上阴影 Carlwave
    asp.net有效使用缓存(转) Carlwave
    《Business Rules Engine Overview》《业务规则引擎概述》write by Mark Kamoski Carlwave
    中国详细省市县自治区名称列表(含access数据库和sql2000备份数据库) Carlwave
  • 原文地址:https://www.cnblogs.com/HocRiser/p/8974434.html
Copyright © 2011-2022 走看看