• POJ 3384 Feng Shui 半平面交


    题目大意:一个人很信“Feng Shui”,他要在房间里放两个圆形的地毯。

    这两个地毯之间可以重叠,可是不能折叠,也不能伸到房间的外面。求这两个地毯可以覆盖的最大范围。并输出这两个地毯的圆心。


    思路:我们当然希望这两个圆形的地毯离得尽量的远,这种话两个圆之间的重叠区域就会越小,总的覆盖区域就越大。

    那我们就先把每一条边向内推进地毯的半径的距离,然后求一次半平面交,这个求出的半平面的交集就是圆心能够取得地方,然后就暴力求出这当中的最远点对即可了。


    CODE:

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define MAX 110
    #define EPS 1e-10
    #define DCMP(a) (fabs(a) < EPS)
    using namespace std;
    
    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);
    	}
    	Point operator *(double a)const {
    		return Point(x * a,y * a);
    	}
    	void Read() {
    		scanf("%lf%lf",&x,&y);
    	}
    }point[MAX],p[MAX],polygen[MAX];
    struct Line{
    	Point p,v;
    	double alpha;
    
    	Line(Point _,Point __):p(_),v(__) {
    		alpha = atan2(v.y,v.x);
    	}
    	Line() {}
    	bool operator <(const Line &a)const {
    		return alpha < a.alpha;
    	}
    }line[MAX],q[MAX];
    
    int points,lines;
    double adjustment;
    
    inline double Cross(const Point &a,const Point &b)
    {
    	return a.x * b.y - a.y * b.x;
    }
    
    inline double Calc(const Point &a,const Point &b)
    {
    	return sqrt((a.x - b.x) * (a.x - b.x) + 
    				(a.y - b.y) * (a.y - b.y));
    }
    
    inline bool OnLeft(const Line &l,const Point &p)
    {
    	return Cross(l.v,p - l.p) >= 0;
    }
    
    inline void MakeLine(const Point &a,const Point &b)
    {
    	Point p = a,v = b - a;
    	Point _v(-v.y / Calc(a,b),v.x / Calc(a,b));
    	p = _v * adjustment + p;
    	line[++lines] = Line(p,v);
    }
    
    inline Point GetIntersection(const Line &a,const Line &b)
    {
    	Point u = a.p - b.p;
    	double temp = Cross(b.v,u) / Cross(a.v,b.v);
    	return a.p + a.v * temp;
    }
    
    int HalfPlaneIntersection()
    {
    	int front = 1,tail = 1;
    	q[tail] = line[1];
    	for(int i = 2;i <= lines; ++i) {
    		while(front < tail && !OnLeft(line[i],p[tail - 1]))	--tail;
    		while(front < tail && !OnLeft(line[i],p[front]))	++front;
    		if(DCMP(Cross(line[i].v,q[tail].v)))
    			q[tail] = OnLeft(line[i],q[tail].p) ? q[tail]:line[i];
    		else	q[++tail] = line[i];
    		if(front < tail)	p[tail - 1] = GetIntersection(q[tail],q[tail - 1]);
    	}
    	while(front < tail && !OnLeft(q[front],p[tail - 1]))	--tail;
    	p[tail] = GetIntersection(q[tail],q[front]);
    	int re = 0;
    	for(int i = front;i <= tail; ++i)
    		polygen[++re] = p[i];
    	return re;
    }
    
    pair<Point,Point> GetFarest(int cnt)
    {
    	double max_length = -1.0;
    	pair<Point,Point> re;
    	for(int i = 1;i <= cnt; ++i)
    		for(int j = i;j <= cnt; ++j)
    			if(Calc(polygen[i],polygen[j]) > max_length) {
    				max_length = Calc(polygen[i],polygen[j]);
    				re.first = polygen[i];
    				re.second = polygen[j];
    			}
    	return re;
    }
    
    int main()
    {
    	cin >> points >> adjustment;
    	for(int i = 1;i <= points; ++i)
    		point[i].Read();
    	for(int i = points;i > 1; --i)
    		MakeLine(point[i],point[i - 1]);
    	MakeLine(point[1],point[points]);
    	sort(line + 1,line + lines + 1);
    	int cnt = HalfPlaneIntersection();
    	pair<Point,Point> re = GetFarest(cnt);
    	printf("%.6lf %.6lf %.6lf %.6lf
    ",re.first.x,re.first.y,re.second.x,re.second.y);
    	return 0;
    }


  • 相关阅读:
    [学习笔记] 网络最大流的HLPP算法
    [学习笔记] LCT 初步
    js中函数的原型及继承
    关于js中函数的一点总结
    关于css实现水平及垂直居中的方法记录
    js基础总结03 --操作数组
    近期学习es6后对变量提升及let和const的一点思考
    用css和js实现侧边菜单栏点击和鼠标滑动特效
    用css或js实现文本输入框的特效
    Jmeter怎样打印日志
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/5253010.html
Copyright © 2020-2023  润新知