POJ 3384 Feng Shui (计算几何+半平面交)

来源:互联网 发布:c语言求平方根函数 编辑:程序博客网 时间:2024/05/31 15:18

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 integersxi and yi each — coordinates of the i-th corner (−1000 ≤xi, yi ≤ 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 x1, y1, x2,y2 to the output file, where (x1, y1) and (x2,y2) 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


将多边形向里面缩距离为 r 的一圈,然后找出最远点对即可

代码:

#include<cstdio>#include<iostream>#include<cstdlib>#include<cstring>#include<algorithm>#include<functional>#include<vector>#include <map>#include<cmath>using namespace std;typedef long long LL;const LL MOD=1e9+7;const double eps=1e-9;const int MAXN=100+23;#define point pair<double,double>#define x first#define y secondvoid output(point p[],int n){    puts("******points:");    for(int i=1;i<=n;i++)    {        printf("%.0f %.0f\n",p[i].x,p[i].y);    }}double cross(point o,point a,point b){    return (a.x-o.x)*(b.y-o.y)-(a.y-o.y)*(b.x-o.x);}double getarea(point p[],int n){    double area=0;    for(int i=2;i<n;i++)    {        area+=(p[i].x-p[1].x)*(p[i+1].y-p[1].y)-(p[i].y-p[1].y)*(p[i+1].x-p[1].x);    }    return area/2.0;}double dist(point a,point b){    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}void getline(double &a,double &b,double &c,point x1,point x2){    a=(x1.y-x2.y);    b=(x2.x-x1.x);    c=-a*x1.x-b*x1.y;}point intersect(double a,double b,double c,point x1,point x2){    double u=fabs(a*x1.x+b*x1.y+c);    double v=fabs(a*x2.x+b*x2.y+c);    return point((x1.x*v+x2.x*u)/(u+v),(x1.y*v+x2.y*u)/(u+v));}int n,last,now;point p1[MAXN],p2[MAXN],p3[MAXN];void cut(double a,double b,double c){    now=0;    for(int i=1;i<=last;i++)    {        if(a*p2[i].x+b*p2[i].y+c<=eps)        {            p3[++now]=p2[i];        }        else        {            if(a*p2[i-1].x+b*p2[i-1].y+c<=eps)            {                p3[++now]=intersect(a,b,c,p2[i],p2[i-1]);            }            if(a*p2[i+1].x+b*p2[i+1].y+c<=eps)            {                p3[++now]=intersect(a,b,c,p2[i],p2[i+1]);            }        }    }    last=now;    for(int i=1;i<=last;i++)p2[i]=p3[i];    p2[last+1]=p3[1];p2[0]=p3[last];}inline void GuiZhengHua(){    //规整化方向,逆时针变顺时针,顺时针变逆时针    for(int i = 1; i <=(n)/2; i++)      swap(p1[i], p1[n-i]);//头文件加iostream}double r;int main(){    while(scanf("%d%lf",&n,&r)!=-1)    {        for(int i=1;i<=n;i++)        {            scanf("%lf%lf",&p1[i].x,&p1[i].y);        }        p1[0]=p1[n];p1[n+1]=p1[1];        for(int i=0;i<=n+1;i++)p2[i]=p1[i];last=n;        for(int i=1;i<=n;i++)        {            double a,b,c;            point t0,t1,t2;            t0=point(p1[i].x-p1[i+1].x,p1[i].y-p1[i+1].y);            double k=r/dist(p1[i],p1[i+1]);            t0.x*=k;            t0.y*=k;            t1=point(p1[i].x-t0.y,p1[i].y+t0.x);            t2=point(p1[i+1].x-t0.y,p1[i+1].y+t0.x);            getline(a,b,c,t1,t2);            cut(a,b,c);        }        int pos1=1,pos2=2;        for(int i=1;i<=last;i++)        {            for(int j=i+1;j<=last;j++)            {                if(dist(p2[i],p2[j])>dist(p2[pos1],p2[pos2]))                {                    pos1=i;                    pos2=j;                }            }        }        printf("%.10f %.10f %.10f %.10f\n",p2[pos1].x,p2[pos1].y,p2[pos2].x,p2[pos2].y);    }    return 0;}

本人蒟蒻,如有错误,还望指正


原创粉丝点击