• 【BZOJ1007】[HNOI2008]水平可见直线 半平面交


    【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

    题解:本人懒,直接用的半平面交。当然由于本题的特殊性质(都是取上半平面),所以我们可以将单调队列换成单调栈。

    由于精度问题,本题需要将eps去掉。

     

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    const int maxn=50010;
    const double alpha=1.23456789;
    struct point
    {
    	double x,y;
    	point() {}
    	point(double a,double b){x=a,y=b;}
    	point operator + (const point &a) const {return point(x+a.x,y+a.y);}
    	point operator - (const point &a) const {return point(x-a.x,y-a.y);}
    	point operator * (const double &a) const {return point(x*a,y*a);}
    	double operator * (const point &a) const {return x*a.y-y*a.x;}
    };
    struct line
    {
    	point p,v;
    	double a;
    	int org;
    	line() {}
    	line(point x,point y,int z){p=x,v=y,a=atan2(v.y,v.x),org=z;}
    }l[maxn];
    int q[maxn],ans[maxn];
    int h,t,n;
    point getp(line l1,line l2)
    {
    	point u=l1.p-l2.p;
    	double temp=(l2.v*u)/(l1.v*l2.v);
    	return l1.p+l1.v*temp;
    }
    bool onlft(line a,point b)
    {
    	return a.v*(b-a.p)>0;
    }
    bool cmp(line a,line b)
    {
    	if(fabs(a.a-b.a)==0)	return !onlft(a,b.p);
    	return a.a<b.a;
    }
    void HPI()
    {
    	sort(l+1,l+n+1,cmp);
    	int i,cnt;
    	for(i=2,cnt=1;i<=n;i++)	if(fabs(l[i].a-l[cnt].a)>0)	l[++cnt]=l[i];
    	h=t=q[1]=1;
    	for(i=2;i<=cnt;i++)
    	{
    		while(h<t&&!onlft(l[i],getp(l[q[t]],l[q[t-1]])))	t--;
    		while(h<t&&!onlft(l[i],getp(l[q[h]],l[q[h+1]])))	h++;
    		q[++t]=i;
    	}
    	//while(h<t&&onlft(l[q[h]],getp(l[q[t]],l[q[t-1]])))	t--;
    	//while(h<t&&onlft(l[q[t]],getp(l[q[h]],l[q[h+1]])))	h++;
    }
    int main()
    {
    	scanf("%d",&n);
    	int i;
    	double a,b;
    	for(i=1;i<=n;i++)	scanf("%lf%lf",&a,&b),l[i]=line(point(0,b),point(1,a),i);
    	HPI();
    	for(i=h;i<=t;i++)	ans[++ans[0]]=l[q[i]].org;
    	sort(ans+1,ans+ans[0]+1);
    	for(i=1;i<=ans[0];i++)	printf("%d ",ans[i]);
    	return 0;
    }

     

  • 相关阅读:
    visual studio------初建一个c++项目流程
    随便写
    C++再修(一)————通过一个头文件,来讲解整个程序的部分概念
    ROS学习记录(四)————怎样建立一个package包?
    XML的学习笔记(一)————基本语法和规范
    C++学习日记(二)————初始字符串类型及封装
    C++学习日记(一)————类与对象
    ROS学习记录(三)————创建一个简单的发布节点和订阅节点
    ROS学习记录(二)————使用smartcar进行仿真(用.xacro文件来运行rviz)
    ROS学习记录(一)————创建简单的机器人模型smartcar
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7500599.html
Copyright © 2020-2023  润新知