1. 程式人生 > >POJ 3384 放地毯【半平面交】

POJ 3384 放地毯【半平面交】

strong -i ros sin init 中一 ref 兩個 tar

<題目鏈接>

題目大意:

給出一個凸多邊形的房間,根據風水要求,把兩個圓形地毯鋪在房間裏,不能折疊,不能切割,可以重疊。問最多能覆蓋多大空間,輸出兩個地毯的圓心坐標。多組解輸出其中一個,題目保證至少可以放入一個圓。

解題分析:

因為放置的圓不能超出多邊形的邊界,所以先將該凸多邊形的各個邊長向內平移 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\n",poly[ansi].x,poly[ansi].y,poly[ansj].x,poly[ansj].y); }

2018-08-03

POJ 3384 放地毯【半平面交】