zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    fullCalendar改造计划之带农历节气节假日的万年历(转)
    Linked List Cycle
    Remove Nth Node From End of List
    Binary Tree Inorder Traversal
    Unique Binary Search Trees
    Binary Tree Level Order Traversal
    Binary Tree Level Order Traversal II
    Plus One
    Remove Duplicates from Sorted List
    Merge Two Sorted Lists
  • 原文地址:https://www.cnblogs.com/refun/p/10454843.html
Copyright © 2011-2022 走看看