ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

poj2540半平面交+判范围

2021-06-02 02:03:55  阅读:186  来源: 互联网

标签:head int eps ++ tail 平面 line poj2540 范围


题意:

在10*10的范围,你每次站在一个点,会告诉你距离目标点变近了还是远了,每次输出可能的范围.

思路:

对于当前p[i]和前一次p[i-1],他的回答等于告诉你在p[i] - > p[i-1]这条线的中垂线的哪一边,先表示出这根中垂线,定义它的左边表示包含部分,然后用远近调整这条线的方向(经过Mid点),加入到半平面交中求面积.

int sgn(double x) {
	if(fabs(x) < eps) return 0;
    return x<0?-1:1;
}
struct Point {
	double x,y;
	Point() {}
	Point(double _x,double _y) {
		x = _x;
		y = _y;
	}
	Point operator +(const Point &b)const {
		return Point(x+b.x,y+b.y);
	}
	Point operator -(const Point &b)const {
		return Point(x - b.x, y - b.y);
	}
	double operator ^(const Point &b)const {
		return x*b.y - y*b.x;
	}
	double operator *(const Point &b)const {
		return x*b.x + y*b.y;
	}
};

double Cross(Point a,Point b) {
	return a.x*b.y-a.y*b.x;
}

typedef Point Vector;
double ss;
struct Line {
	Point s,e;
	double k;
	Line() {}
	Line(Point _s,Point _e) {
		s = _s;
		e = _e;
		k = atan2(e.y - s.y,e.x - s.x);
	}
	Point operator &(const Line &b)const {
		Point res = s;
		double t = ((s - b.s)^(b.s - b.e))/((s - e)^(b.s - b.e));
		res.x += (e.x - s.x)*t;
		res.y += (e.y - s.y)*t;
		return res;
	}
};
//半平面交,直线的左边代表有效区域
bool HPIcmp(Line a,Line b) {
	if(fabs(a.k - b.k) > eps)return a.k < b.k;
	return ((a.s - b.s)^(b.e - b.s)) < 0;
}

Line Q[1010];
void HPI(Line line[], int n, Point res[], int &resn) {
	int tot = n;
	sort(line,line+n,HPIcmp);
	tot = 1;
	for(int i = 1; i < n; i++)
		if(fabs(line[i].k - line[i-1].k) > eps)
			line[tot++] = line[i];
	int head = 0, tail = 1;
	Q[0] = line[0];
	Q[1] = line[1];
	resn = 0;
	for(int i = 2; i < tot; i++) {
		if(fabs((Q[tail].e-Q[tail].s)^(Q[tail-1].e-Q[tail-1].s)) < eps || fabs((Q[head].e-Q[head].s)^(Q[head+1].e-Q[head+1].s)) < eps)
			return;
		while(head < tail && (((Q[tail]&Q[tail-1]) - line[i].s)^(line[i].e-line[i].s)) > eps)
			tail--;
		while(head < tail && (((Q[head]&Q[head+1]) - line[i].s)^(line[i].e-line[i].s)) > eps)
			head++;
		Q[++tail] = line[i];
	}
	while(head < tail && (((Q[tail]&Q[tail-1]) - Q[head].s)^(Q[head].e-Q[head].s)) > eps)
		tail--;
	while(head < tail && (((Q[head]&Q[head-1]) - Q[tail].s)^(Q[tail].e-Q[tail].e)) > eps)
		head++;
	if(tail <= head + 1)return;
	for(int i = head; i < tail; i++)
		res[resn++] = Q[i]&Q[i+1];
	if(head < tail - 1)
		res[resn++] = Q[head]&Q[tail];

	ss=0;
	for(int i=0; i<resn; i++) {
		int j=(i+1)%resn;
		ss += res[i]^res[j];
	}
	ss/=2;
}
Point p[1010];
Line line[1010];
int n,cnt;
char op[10];
void init() {
	n=0;
	line[n++]=Line(Point(0,0),Point(10,0));
	line[n++]=Line(Point(10,0),Point(10,10));
	line[n++]=Line(Point(10,10),Point(0,10));
	line[n++]=Line(Point(0,10),Point(0,0));
}

Point getMid(Point a,Point b) {
	Point res;
	res.x = (a.x+b.x)/2;
	res.y = (a.y+b.y)/2;
	return res;
}
Point pp[N];
void work() {
	init();
	cnt=0;
	int flag=0;
	p[0].x=p[0].y=0;
	while(~scanf("%lf%lf%s",&p[cnt].x,&p[cnt].y,op)) {
		if(op[0]=='S')flag=1;
		Point v=p[cnt]-p[cnt-1];
		v=Point(v.y,-v.x);
		Point Mid = getMid(p[cnt],p[cnt-1]);
//		cout << Mid.x << ' ' << Mid.y << endl;
		if(sgn(Cross(v,p[cnt-1]-Mid))<0)v=Point(-v.x,-v.y);   //p[cnt-1]在直线左边
		if(op[0] == 'H')v=Point(-v.x,-v.y);
		line[n++]=Line(Mid,Mid+v);
		if(flag)printf("0.00\n");
		else {
			//计算半平面交
			int resn;
			ss=0;
			HPI(line,n,pp,resn);
			printf("%.2f\n",ss);
		}
		cnt++;
	}
}

标签:head,int,eps,++,tail,平面,line,poj2540,范围
来源: https://www.cnblogs.com/LaiYiC/p/14839495.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有