题意:每组给出多边形的n个顶点坐标和两块圆形地毯的半径,求两块地毯覆盖多边形的最大面积是圆点坐标;
思路:将多边形向内缩进一个圆半径,圆点就在变化后的多边形上,且为其上的相距最远的两个点;数据与poj样例完全不一样居然能过。。。
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const double epsi=1e-10; const int maxn=1010; const double pi=acos(-1.0); inline int sign(const double &x){ if(x>epsi) return 1; if(x<-epsi) return -1; return 0; } struct point{ double x,y; point(double xx=0,double yy=0):x(xx),y(yy){} point operator +(const point &op2) const{ return point(x+op2.x,y+op2.y); } point operator -(const point &op2) const{ return point(x-op2.x,y-op2.y); } double operator *(const point &op2) const{ return x*op2.x+y*op2.y; } point operator *(const double &d) const{ return point(x*d,y*d); } point operator /(const double &d) const{ return point(x/d,y/d); } double operator ^(const point &op2) const{ return x*op2.y-y*op2.x; } bool operator ==(const point &op2) const{ return sign(x-op2.x)==0&&sign(y-op2.y)==0; } }; int n; double r; point p[maxn]; int t[2]; point plane[2][maxn],q1,q2; inline double sqr(const double &x){ return x*x; } inline double mul(const point &p0,const point &p1,const point &p2){ return (p1-p0)^(p2-p0); } inline double dot(const point &p0,const point &p1,const point &p2){ return (p1-p0)*(p2-p0); //p1p0与p2p0的点积 } inline double dis2(const point &p0,const point &p1){ return sqr(p0.x-p1.x)+sqr(p0.y-p1.y); } inline double dis(const point &p0,const point &p1){ return sqrt(dis2(p0,p1)); } inline double dis(const point &p0,const point &p1,const point &p2){ if(sign(dot(p1,p0,p2)<0)) return dis(p0,p1); //若p1p0与p1p2的夹角超过90度,返回p1p0 if(sign(dot(p2,p0,p1))<0) return dis(p0,p2); //若p2p0与p2p1的夹角超过90度,返回p2p0 return fabs(mul(p0,p1,p2)/dis(p1,p2)); //返回p0至p1p2的垂线长度 } inline point rotate(const point &p,const double &ang){ //点p旋转ang角度后的点 return point(p.x*cos(ang)-p.y*sin(ang),p.x*sin(ang)+p.y*cos(ang)); } inline void translation(const point &p1,const point &p2,const double &d,point &q1,point &q2){ q1=p1+rotate(p2-p1,pi/2)*d/dis(p1,p2); //p2p1向内推进d后形成直线q2q1 q2=q1+p2-p1; } inline void cross(const point &p1,const point &p2,const point &p3,const point &p4,point &p){ double a1=mul(p1,p3,p4),a2=mul(p2,p3,p4); p.x=(a1*p2.x-a2*p1.x)/(a1-a2); p.y=(a1*p2.y-a2*p1.y)/(a1-a2); //利用公式计算交点 } inline int half_plane_cross(point *a,int n,point *b,const point &p1,const point &p2){ int newn=0; for(int i=0,j;i<n;++i){ if(sign(mul(a[i],p1,p2))>=0){ b[newn++]=a[i]; continue; } j=i-1; if(j==-1) j=n-1; //计算i的左相邻点j if(sign(mul(a[j],p1,p2))>0){ cross(p1,p2,a[j],a[i],b[newn++]); } j=i+1; if(j==n) j=0; //计算i右相邻点j if(sign(mul(a[j],p1,p2))>0) cross(p1,p2,a[j],a[i],b[newn++]); } return newn; } int main() { scanf("%d%lf",&n,&r); for(int i=0;i<n;i++) scanf("%lf%lf",&p[i].x,&p[i].y); p[n]=p[0]; int o1=0,o2; t[0]=4; plane[0][0]=point(-1e3,-1e3); plane[0][1]=point(1e3,-1e3); plane[0][2]=point(1e3,1e3); plane[0][3]=point(-1e3,1e3); for(int i=0;i<n;i++){ o2=o1^1; translation(p[i+1],p[i],r,q1,q2); t[o2]=half_plane_cross(plane[o1],t[o1],plane[o2],q1,q2); o1=o2; } double maxd=-1,curd; for(int i=0;i<t[o1];i++) for(int j=i;j<t[o1];j++){ curd=dis2(plane[o1][i],plane[o1][j]); if(sign(curd-maxd)>0){ maxd=curd; q1=plane[o1][i];q2=plane[o1][j]; } } printf("%.4f %.4f %.4f %.4f ",q1.x,q1.y,q2.x,q2.y); return 0; }