• 【BZOJ1007】【HNOI2008】水平可见直线


    依旧看黄学长代码,不过这回是看完后自己写的

    原题:

     在xoy直角坐标平面上有n条直线L1,L2,...Ln,若在y值为正无穷大处往下看,能见到Li的某个子线段,则称Li为
    可见的,否则Li为被覆盖的.
    例如,对于直线:
    L1:y=x; L2:y=-x; L3:y=0
    则L1和L2是可见的,L3是被覆盖的.
    给出n条直线,表示成y=Ax+B的形式(|A|,|B|<=500000),且n条直线两两不重合.求出所有可见的直线.

    0 < N < 50000

    给线段求下凸包,还算比较简单把

    用栈,首先根据斜率排个序,这里建议如果斜率相等呢么y轴上截距递减,这样如果要插入的直线斜率和栈顶斜率相等直接停止就行了

    如果要插入的直线和栈中top-1的交点在栈中top和栈中top-2的交点的左边,呢么top--

    为什么呐

    手玩三条直线很容易看出来,图比较好画我就画一下吧(我也只能画简单的图了

    怎么计算交点呐

    因为是很简单的x=kx+b,这就是小学数学,为了增加文章的篇幅来扯一扯 _(:3 」∠)_

    就是解二元一次方程组,{y=k1x+b1,y=k2x+b2},下面减上面,(k2-k1)x=b1-b2,x=(b1-b2)/(k2-k1)

    然后随便搞一搞就行了,最后用bool记录答案来保证id递增

    小技巧:fabs是计算浮点数的绝对值,注意fabs计算的并不是差的绝对值,也就是说应该是fabs(a-b)而不是fabs(a,b),需要cmath

    我看黄学长和另一个人的代码比x的时候都是直接<=,算时x返回是double啊不是不能直接=么,然而还是过了,不知道为什么

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 using namespace std;
     7 int read(){int z=0,mark=1;  char ch=getchar();
     8     while(ch<'0'||ch>'9'){if(ch=='-')mark=-1;  ch=getchar();}
     9     while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0';  ch=getchar();}
    10     return z*mark;
    11 }
    12 bool deng(double x,double y){  return fabs(x-y)<1e-8;}//fabs传的是绝对值,所以不能fabs(a-b)
    13 int n;  struct cdd{double k,b;  int id;}a[51000];//y=kx+b
    14 bool compare(cdd x,cdd y){  return (deng(x.k,y.k)) ? (x.b>y.b) : (x.k<y.k);}
    15 bool ans[51000];
    16 cdd zhan[51000];  int top=0;
    17 double get_x(cdd x,cdd y){  return (x.b-y.b)/(y.k-x.k);}
    18 void insert(cdd x){
    19     if(deng(x.k,zhan[top].k))  return ;
    20     while(top>1 && get_x(x,zhan[top-1]) <= get_x(zhan[top],zhan[top-1]))  top--;
    21     zhan[++top]=x;
    22 }
    23 int main(){//freopen("ddd.in","r",stdin);
    24     memset(ans,0,sizeof(ans));
    25     cin>>n;
    26     for(int i=1;i<=n;i++)  scanf("%lf%lf",&a[i].k,&a[i].b),a[i].id=i;
    27     sort(a+1,a+n+1,compare);
    28     a[0].k=a[0].b=-999999999;
    29     for(int i=1;i<=n;i++)  insert(a[i]);
    30     for(int i=1;i<=top;i++)  ans[zhan[i].id]=true;
    31     for(int i=1;i<=n;i++)if(ans[i])  printf("%d ",i);
    32     cout<<endl;
    33     return 0;
    34 }
    View Code
  • 相关阅读:
    数论学习之乘法逆元
    数论学习之扩展欧几里得
    数论学习之费马与欧拉
    一次函数
    东南西北
    接水问题
    脱水缩合
    背单词
    单词接龙
    字符串,字符数组
  • 原文地址:https://www.cnblogs.com/JSL2018/p/5917130.html
Copyright © 2020-2023  润新知