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++;
	}
}
上一篇:北汇信息MES系统助力浙江万达EPS事业部打造可视化车间


下一篇:LFM信号的模糊函数LFM_ambg