• BZOJ1007:[HNOI2008]水平可见直线(计算几何)


    Description

    在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条直线两两不重合.求出所有可见的直线.

    Input

    第一行为N(0 < N < 50000),接下来的N行输入Ai,Bi

    Output

    从小到大输出可见直线的编号,两两中间用空格隔开,最后一个数字后面也必须有个空格

    Sample Input

    3
    -1 0
    1 0
    0 0

    Sample Output

    1 2

    Solution

    首先把直线按照斜率排序,再用个栈维护一下。

    画个图可以发现,如果直线$i$和直线$stack[top]$的交点在直线$stack[top-1]$的左边,那么$stack[top]$就可以被弹出了。随便判判就好了。

    Code

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #define N (50009)
     6 #define INF (1e18)
     7 using namespace std;
     8 
     9 struct Vector
    10 {
    11     double x,y;
    12     Vector(double xx=0,double yy=0)
    13     {
    14         x=xx; y=yy;
    15     }
    16 }p[N];
    17 typedef Vector Point;
    18 
    19 struct Line
    20 {
    21     double k,b;
    22     Point x,y;
    23     int id;
    24     bool operator < (const Line &a) const
    25     {
    26         return k==a.k?b>a.b:k>a.k;
    27     }
    28     bool operator == (const Line &a) const
    29     {
    30         return k==a.k && b==a.b;
    31     }
    32 }L[N],stack[N];
    33 
    34 int n,k,b,ans[N],top;
    35 
    36 double Cross(Vector a,Vector b) {return a.x*b.y-a.y*b.x;}
    37 Vector operator - (Vector a,Vector b) {return Vector(a.x-b.x,a.y-b.y);}
    38 
    39 inline int read()
    40 {
    41     int x=0,w=1; char c=getchar();
    42     while (!isdigit(c)) {if (c=='-') w=-1; c=getchar();}
    43     while (isdigit(c)) x=x*10+c-'0', c=getchar();
    44     return x*w;
    45 }
    46 
    47 Point Line_Cross(Line u,Line v)
    48 {
    49     Point ans;
    50     ans.x=(v.b-u.b)/(u.k-v.k);
    51     ans.y=u.k*ans.x+u.b;
    52     return ans;
    53 }
    54 
    55 int main()
    56 {
    57     n=read();
    58     for (int i=1; i<=n; ++i)
    59     {
    60         k=read(); b=read();
    61         L[i]=(Line){k,b};
    62         L[i].x=(Point){0,b};
    63         L[i].y=(Point){1,k+b};
    64         L[i].id=i;
    65     }
    66     sort(L+1,L+n+1);
    67     for (int i=1; i<=n; ++i)
    68     {
    69         if (top && L[i].k==stack[top].k) continue;
    70         while (top>=2)
    71         {
    72             Point p=Line_Cross(stack[top],L[i]);
    73             if (Cross(stack[top-1].x-p,stack[top-1].y-p)>0) break;
    74             top--;
    75         }
    76         stack[++top]=L[i];
    77     }
    78     for (int i=1; i<=top; ++i) ans[stack[i].id]=1;
    79     for (int i=1; i<=n; ++i) if (ans[i]) printf("%d ",i);
    80 }
  • 相关阅读:
    oracle一些常用的单记录函数
    javascript闭包(closure)
    【Matlab开发】matlab中bar绘图设置与各种距离度量
    【Matlab开发】matlab中bar绘图设置与各种距离度量
    【Matlab开发】matlab中norm范数以及向量点积、绘图设置相关
    【Matlab开发】matlab中norm范数以及向量点积、绘图设置相关
    【编程开发】opencv实现对Mat中某一列或某一行的元素进行normalization
    【编程开发】opencv实现对Mat中某一列或某一行的元素进行normalization
    【编程开发】C语言中随机数rand使用注意事项
    【编程开发】C语言中随机数rand使用注意事项
  • 原文地址:https://www.cnblogs.com/refun/p/10454843.html
Copyright © 2020-2023  润新知