P3194 水平可见直线 计算几何+单调栈

单调栈存放直线,把直线按斜率升序排序枚举 l i l_i li与栈顶直线的交点如果在栈顶与次栈顶的交点左边,那么栈顶代表的直线是不可视的,弹出。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;

const double eps = 1e-8;
const double inf = 1e20;
const int N = 50050;
int sgn(double x){
	if(fabs(x) < eps) return 0;
	if(x > 0) return 1;
	return -1;
}

struct Point{
	double x, y;
	Point(double x = 0, double y = 0):x(x), y(y){
	}
	
}last;
struct Line{
	double a, b;
	int id;
	Line(double a = 0, double b = 0):a(a), b(b){
	}
	void input(int x){
		id = x;
		scanf("%lf%lf", &a, &b);
	}
	Point operator^ (const Line& p) const{
		if(a == p.a) return Point(inf, inf);
		double t = (p.b-b)/(a-p.a);
		return Point(t, a*t+b);
	} 
}l[N], st[N];

bool cmp(Line& l1, Line& l2){
	if(sgn(l1.a-l2.a)) return sgn(l1.a-l2.a)<0;
	return sgn(l1.b-l2.b)>0;
}
bool cmp1(Line& l1, Line& l2){
	return l1.id < l2.id;
}
int tot;
int main(){
	int n;
	scanf("%d", &n);
	for(int i = 1; i <= n; i++) l[i].input(i);
	sort(l+1, l+n+1, cmp); 
	for(int i = 1; i <= n; i++){
		if(tot == 0) {
			st[++tot] = l[i];
			last = Point(-inf, -inf);
			continue;
		}
		if(sgn(st[tot].a-l[i].a) == 0) continue;
		
		Point ne = st[tot]^l[i];
		while(sgn(ne.x-last.x) <= 0 && tot > 1){
			--tot;
			last = st[tot]^st[tot-1];
			ne = st[tot]^l[i];
		}
		last = l[i]^st[tot];
		st[++tot] = l[i];
	}
	sort(st+1, st+tot+1, cmp1);
	for(int i = 1; i <= tot; i++) printf("%d ", st[i].id);
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值