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

    HINT

    Source

    Solution

      按斜率从小到大给直线排序,维护一个下凸壳

      要把新加的线与凸壳的交点以右的直线删掉,因为新加的线一定在它与它之前的线组成的凸壳中

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const double EPS = 1e-8;
     4 struct line
     5 {
     6     int id;
     7     double k, b;
     8     bool operator< (const line &rhs) const
     9     {
    10         return fabs(k - rhs.k) < EPS ? b < rhs.b : k < rhs.k;
    11     }
    12 }a[100005];
    13 int sta[100005], ans[100005];
    14  
    15 double getx(int x)
    16 {
    17     return (a[sta[x]].b - a[sta[x - 1]].b) / (a[sta[x - 1]].k - a[sta[x]].k);
    18 }
    19  
    20 int main()
    21 {
    22     int n, top;
    23     cin >> n;
    24     for(int i = 1; i <= n; ++i)
    25     {
    26         cin >> a[i].k >> a[i].b;
    27         a[i].id = i;
    28     }
    29     sort(a + 1, a + n + 1);
    30     sta[top = 1] = 1;
    31     for(int i = 2; i <= n; ++i)
    32     {
    33         sta[++top] = i;
    34         while(top > 1)
    35             if(fabs(a[i].k - a[sta[top - 1]].k) < EPS) sta[--top] = i;
    36             else if(top > 2 && getx(top) - getx(top - 1) < EPS)
    37                 sta[--top] = i;
    38             else break;
    39     }
    40     for(int i = 1; i <= top; ++i)
    41         ans[i] = a[sta[i]].id;
    42     sort(ans + 1, ans + top + 1);
    43     for(int i = 1; i <= top; ++i)
    44         cout << ans[i] << ' ';
    45     cout << endl;
    46     return 0;
    47 }
    View Code
  • 相关阅读:
    小酌一下:pipenv 基本用法
    sql2008使用您对无法重新创建的表进行了更改或者启用了“阻止保存重新创建表的更改”
    Join操作基本:外连接、自然连接、内连接
    用dataReader获取datetime类型完整精度的时间字串
    c# MesageBox
    判断当前时间是否在一个时间段内
    c# 根据当前时间获取,本周,本月,本季度,月初,月末,各个时间段
    sql Convert函数
    c# MD5方法总结
    wml跳转
  • 原文地址:https://www.cnblogs.com/CtrlCV/p/5585497.html
Copyright © 2011-2022 走看看