zoukankan      html  css  js  c++  java
  • 题解报告——水平可见直线

    传送门

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

    【输入】

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

    【输出】

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

    【输入样例】

    3
    -1 0
    1 0
    0 0

    【输出样例】

    1 2

     【思路分析】

    首先我们可以得出,我们最后从上方看到的直线排布,一定是一个类似于下凸包的形状,将这些直线按其k值从小到大排一下序,如果k相同则按b从小到大排序,依次加到栈中,我们判断一下交点的位置关系,如下图:

    我们发现如果line[i]与top的交点的x小于line[i]与top-1的交点的x,那么top这条直线就被完全覆盖了,就要将其弹出。

    最后我们就统计一下留在栈中的直线即可


    【代码实现】

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<cmath>
     5 using namespace std;
     6 const int N=5e4+5;
     7 struct sd{
     8     double k,b;int id;
     9 }line[N],stk[N];
    10 int n,top;
    11 bool cmp(sd a,sd b)
    12 {
    13     if(a.k==b.k) return a.b<b.b;
    14     return a.k<b.k;
    15 }
    16 bool CMP(sd a,sd b){return a.id<b.id;}
    17 double mix(sd x,sd y){return (y.b-x.b)/(x.k-y.k);}
    18 int main()
    19 {
    20     scanf("%d",&n);
    21     for(int i=1;i<=n;i++)
    22     scanf("%lf %lf",&line[i].k,&line[i].b),line[i].id=i;
    23     sort(line+1,line+1+n,cmp);
    24     for(int i=1;i<=n;i++)
    25     {
    26         while(top>0&&line[i].k==stk[top].k) top--;
    27         while(top>1&&mix(line[i],stk[top])<=mix(line[i],stk[top-1])) 
    28         top--;
    29         stk[++top]=line[i];
    30     }
    31     sort(stk+1,stk+1+top,CMP);
    32     for(int i=1;i<=top;i++) printf("%d ",stk[i].id);
    33     return 0;
    34 }
  • 相关阅读:
    几个华为5300交换机故障的意思和可能产生的原因
    怎么让win7右下角只显示时间不显示日期 ?(可行)
    Linux下LDAP统一认证解决方案
    教你如何禁用U盘、屏蔽USB端口的三种方法
    开机自动启动一个新建文件夹
    端口
    输//ip提示找不到应用程序
    java单向加密算法小结(2)--MD5哈希算法
    java单向加密算法小结(1)--Base64算法
    Git初探--笔记整理和Git命令详解
  • 原文地址:https://www.cnblogs.com/genius777/p/9220891.html
Copyright © 2011-2022 走看看