POJ 3384 放地毯半平面交
Posted 00isok
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 3384 放地毯半平面交相关的知识,希望对你有一定的参考价值。
<题目链接>
题目大意:
给出一个凸多边形的房间,根据风水要求,把两个圆形地毯铺在房间里,不能折叠,不能切割,可以重叠。问最多能覆盖多大空间,输出两个地毯的圆心坐标。多组解输出其中一个,题目保证至少可以放入一个圆。
解题分析:
因为放置的圆不能超出多边形的边界,所以先将该凸多边形的各个边长向内平移 r 的距离,然后对这些平移后的直线用半平面交去切割原多边形,切割后得到的区域就是两圆圆心所在的区域,然后遍历这个切割后的多边形的各个顶点,距离最远的两个顶点就是这两圆的圆心。
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; #define N 10005 const double pi=acos(-1.0); const double inf=1e9; const double eps=1e-12; int dcmp(double x) { if (x<=eps&&x>=-eps) return 0; return (x>0)?1:-1; } struct Vector { double x,y; Vector(double X=0,double Y=0) { x=X,y=Y; } }; typedef Vector Point; Vector operator + (Vector a,Vector b) {return Vector(a.x+b.x,a.y+b.y);} Vector operator - (Vector a,Vector b) {return Vector(a.x-b.x,a.y-b.y);} Vector operator * (Vector a,double p) {return Vector(a.x*p,a.y*p);} int n,cnt,ncnt,ansi,ansj; double x,y,r,ans; Point p[N],poly[N],npoly[N]; double Dot(Vector a,Vector b) { return a.x*b.x+a.y*b.y; } double Cross(Vector a,Vector b) { return a.x*b.y-a.y*b.x; } double Len(Vector a) { return sqrt(Dot(a,a)); } Vector rotate(Vector a,double rad) { return Vector(a.x*cos(rad)-a.y*sin(rad),a.x*sin(rad)+a.y*cos(rad)); } bool insLS(Point A,Point B,Point C,Point D) { Vector v=B-A,w=C-A,u=D-A; return dcmp(Cross(v,w))!=dcmp(Cross(v,u)); } Point GLI(Point P,Vector v,Point Q,Vector w) { Vector u=P-Q; double t=Cross(w,u)/Cross(v,w); return P+v*t; } void init() { cnt=0; poly[++cnt]=Point(inf,inf); poly[++cnt]=Point(inf,-inf); poly[++cnt]=Point(-inf,-inf); poly[++cnt]=Point(-inf,inf); } void halfp(Point A,Point B) { ncnt=0; Point C,D; for (int i=1;i<=cnt;++i) { C=poly[i%cnt+1]; D=poly[(i+1)%cnt+1]; if (dcmp(Cross(B-A,C-A))<=0) npoly[++ncnt]=C; if (insLS(A,B,C,D)) npoly[++ncnt]=GLI(A,B-A,C,D-C); } cnt=ncnt; for (int i=1;i<=cnt;++i) poly[i]=npoly[i]; } int main() { scanf("%d%lf",&n,&r); for (int i=1;i<=n;++i) { scanf("%lf%lf",&x,&y); p[i]=Point(x,y); } init(); for (int i=1;i<=n;++i) { Point A=p[i%n+1]; Point B=p[(i+1)%n+1]; Vector v=B-A; Vector w=rotate(v,-pi/2.0); w=w*(r/Len(w)); Point C=A+w; Point D=C+v; halfp(C,D); } ansi=ansj=1; for (int i=1;i<=cnt;++i) for (int j=i+1;j<=cnt;++j) { double dis=Len(poly[i]-poly[j]); if (dcmp(dis-ans)>0) { ans=dis; ansi=i,ansj=j; } } printf("%.4lf %.4lf %.4lf %.4lf ",poly[ansi].x,poly[ansi].y,poly[ansj].x,poly[ansj].y); }
2018-08-03
以上是关于POJ 3384 放地毯半平面交的主要内容,如果未能解决你的问题,请参考以下文章