• 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
    ");
    		else {
    			//计算半平面交
    			int resn;
    			ss=0;
    			HPI(line,n,pp,resn);
    			printf("%.2f
    ",ss);
    		}
    		cnt++;
    	}
    }
    
  • 相关阅读:
    传奇版本自动穿背包中的装备脚本
    MaxM2引擎各种人物触发脚本
    异或加密解密代码
    中元节
    网络加密
    MCMD Commander 命令解释及说明
    Ubuntu字符界面与图形界面切换
    传奇服务端各文件用途说明
    传奇数据库说明
    传奇MAP地图说明
  • 原文地址:https://www.cnblogs.com/LaiYiC/p/14839495.html
Copyright © 2020-2023  润新知