• BZOJ 1007 HNOI 2008 水平可见直线 计算几何+栈


    题目大意:给出一些笛卡尔系中的一些直线,问从(0,+∞)向下看时能看到哪些直线。


    思路:半平面交可做,可是显然用不上。

    类似于求凸包的思想,维护一个栈。

    先将全部直线依照k值排序。然后挨个压进去,遇到有前一个交点被挡住的话就先弹栈。

    比較闹心的是去重。我的方法是压栈之前先去重,然后在处理。


    CODE:

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define MAX 50010
    #define EPS 1e-5
    using namespace std;
    
    inline bool dcmp(double a,double b);
    
    struct Point{
    	double x,y;
    	
    	Point(double _ = 0,double __ = 0):x(_),y(__) {}
     	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);
    	}
    };
    struct Line{
    	double k,b;
    	int _id;
    	
    	bool operator <(const Line &a)const {
    		if(dcmp(k,a.k))	return b < a.b;
    		return k < a.k;
    	}
    }line[MAX],_line[MAX];
    
    int lines;
    int top;
    Line *stack[MAX]; 
    Point intersection[MAX];
    
    bool ans[MAX];
    
    inline Point GetIntersection(const Line &l1,const Line &l2);
    inline bool Under(const Line &l,const Point &p);
    
    int main()
    {
    	cin >> lines;
    	for(int i = 1;i <= lines; ++i) {
    		scanf("%lf%lf",&line[i].k,&line[i].b);
    		line[i]._id = i;
    	}
    	sort(line + 1,line + lines + 1);
    	int cnt = 0;
    	for(int i = 1;i <= lines; ++i) {
    		if(dcmp(line[i].k,line[i + 1].k))	continue;
    		_line[++cnt] = line[i];
    	}
    	stack[++top] = &_line[1];
    	stack[++top] = &_line[2];
    	intersection[top - 1] = GetIntersection(_line[1],_line[2]);
    	for(int i = 3;i <= cnt; ++i) {
    		if(i != cnt && _line[i].k == _line[i + 1].k)	continue;
    		while(top > 1 && Under(_line[i],intersection[top - 1]))	--top;
    		stack[++top] = &_line[i];
    		intersection[top - 1] = GetIntersection(*stack[top],*stack[top - 1]);
    	}
    	for(int i = 1;i <= top; ++i)
    		ans[stack[i]->_id] = true;
    	for(int i = 1;i <= lines; ++i)
    		if(ans[i])	printf("%d ",i);
    	return 0;
    }
    
    inline bool dcmp(double a,double b)
    {
    	return fabs(a - b) < EPS;
    }
    
    inline Point GetIntersection(const Line &l1,const Line &l2)
    {
    	Point re;
    	re.x = (l2.b - l1.b) / (l1.k - l2.k);
    	re.y = re.x * l1.k + l1.b;
    	return re;
    }
    
    inline bool Under(const Line &l,const Point &p)
    {
    	if(l.k * p.x + l.b > p.y || dcmp(l.k * p.x + l.b,p.y))	return true;
    	return false;
    }


  • 相关阅读:
    我看到的我未曾是你们看到的我。
    nagios状态数据更新不及时问题
    Ubuntu下安装 nagiosgraph报错处理
    禁止、允许PING
    windows批量关机
    [转载]div仿框架(B/S结构软件界面)详解[非quirks模式全兼容]
    rrdtool错误attempt to put segment in horiz list twice
    命令参考大全 iostat
    SAP学习手册
    顾问成长之路
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/5139138.html
Copyright © 2020-2023  润新知