POJ 3384: Feng Shui 半平面交

Feng Shui
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 6095 Accepted: 1832 Special Judge

Description

Feng shui is the ancient Chinese practice of placement and arrangement of space to achieve harmony with the environment. George has recently got interested in it, and now wants to apply it to his home and bring harmony to it.

There is a practice which says that bare floor is bad for living area since spiritual energy drains through it, so George purchased two similar round-shaped carpets (feng shui says that straight lines and sharp corners must be avoided). Unfortunately, he is unable to cover the floor entirely since the room has shape of a convex polygon. But he still wants to minimize the uncovered area by selecting the best placing for his carpets, and asks you to help.

You need to place two carpets in the room so that the total area covered by both carpets is maximal possible. The carpets may overlap, but they may not be cut or folded (including cutting or folding along the floor border) — feng shui tells to avoid straight lines.

Input

The first line of the input file contains two integer numbers n and r — the number of corners in George’s room (3 ≤ n ≤ 100) and the radius of the carpets (1 ≤ r ≤ 1000, both carpets have the same radius). The following n lines contain two integers xi and yi each — coordinates of the i-th corner (−1000 ≤ xiyi ≤ 1000). Coordinates of all corners are different, and adjacent walls of the room are not collinear. The corners are listed in clockwise order.

Output

Write four numbers x1y1x2y2 to the output file, where (x1y1) and (x2y2) denote the spots where carpet centers should be placed. Coordinates must be precise up to 4 digits after the decimal point.

If there are multiple optimal placements available, return any of them. The input data guarantees that at least one solution exists.

Sample Input

#15 2 -2 0 -5 3 0 8 7 3 5 0
#24 3 0 0 0 8 10 8 10 0

Sample Output

#1-2 3 3 2.5
#23 5 7 3

Hint


半平面交找到圓心可以放置的位置

即多邊形的核

之後再用核內最遠的兩點做圓心即可


#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<set>
#include<map>
using namespace std;

typedef double db;

inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
void print(int x)
{if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar(x%10+'0');}

const int N=110;
const db eps=1e-8,pi=acos(-1);

int n;
db R;

struct point
{
	db x,y;
	
	friend point operator +(const point &a,const point &b)
	{return (point){a.x+b.x,a.y+b.y};}
	
	friend point operator -(const point &a,const point &b)
	{return (point){a.x-b.x,a.y-b.y};}
	
	friend point operator *(db x,const point &a)
	{return (point){a.x*x,a.y*x};}
	
	friend db dis(const point &a,const point &b)
	{return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
	
	friend db cross(const point &x,const point &y,const point &bas)
	{
		point a(x-bas),b(y-bas);
		return a.x*b.y-a.y*b.x;
	}
}p[N];

int scnt;
struct segment
{
	point X,Y;db angle;
	
	friend bool operator <(const segment &a,const segment &b)
	{
		if(abs(a.angle-b.angle)<eps) return cross(a.X,a.Y,b.X)>0;
		return a.angle<b.angle;
	}
	
	friend point get_node(const segment &a,const segment &b)
	{
		db S[2];
		point res;
		S[0]=cross(a.X,a.Y,b.X);
		S[1]=cross(a.Y,a.X,b.Y);
		res.x=(b.Y.x*S[0]+b.X.x*S[1])/(S[0]+S[1]);
		res.y=(b.Y.y*S[0]+b.X.y*S[1])/(S[0]+S[1]);
		return res;
	}
	
}seg[N];

inline void add_seg(const point &a,const point &b)
{
	// proportion
	db pro=R/dis(a,b);
	seg[++scnt].X.x=a.x-pro*(b-a).y;
	seg[scnt].X.y=a.y+pro*(b-a).x;
	seg[scnt].Y=seg[scnt].X+(b-a);
	seg[scnt].angle=atan2(seg[scnt].Y.y-seg[scnt].X.y,seg[scnt].Y.x-seg[scnt].X.x);
}

bool check(int a,int b,int c)
{
	point tmp(get_node(seg[a],seg[b]));
	return cross(seg[c].X,seg[c].Y,tmp)<0;
}

int top,q[N];
point st[N];

void hpi()
{
	register int i,tot(1),head(0),tail(2);
	sort(seg+1,seg+1+scnt);
	for(i=2;i<=scnt;++i)
		if(abs(seg[i].angle-seg[tot].angle)>eps)
			seg[++tot]=seg[i];
	q[0]=1;q[1]=2;
	for(i=3;i<=tot;++i)
	{
		while(head<tail-1 && check(q[tail-1],q[tail-2],i)) tail--;
		while(head<tail-1 && check(q[head],q[head+1],i)) head++;
		q[tail++]=i;
	}
	while(head<tail-1 && check(q[tail-1],q[tail-2],q[head])) tail--;
	while(head<tail-1 && check(q[head],q[head+1],q[tail-1])) head++;
	q[tail]=q[head];
	for(i=head;i<tail;++i)
		st[++top]=get_node(seg[q[i]],seg[q[i+1]]);
}

int main()
{
	n=read();scanf("%lf",&R);
	register int i,j;
	for(i=n;i;--i) p[i].x=read(),p[i].y=read();
	p[n+1]=p[1];
	for(i=1;i<=n;++i) add_seg(p[i],p[i+1]);
	hpi();
	db tmp(-1);
	int ans[2];
	for(i=1;i<top;++i)
		for(j=i+1;j<=top;++j)
		{
			if(tmp<dis(st[i],st[j]))
			{
				tmp=dis(st[i],st[j]);
				ans[0]=i,ans[1]=j;
			}
		}
	printf("%.4f %.4f %.4f %.4f\n",st[ans[0]].x,st[ans[0]].y,st[ans[1]].x,st[ans[1]].y);
	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章