圆与凸多边形交(圆心严格在多边形内):圆心和每一条边进行三角剖分,每次仅处理在这个三角形里的面积。我是初始整个圆,然后删掉圆在多边形外的部分。少考虑一种情况少了两个continue,wa了一版。。。
精度PS1:这题eps(假设我用way2)设为1e-6~1e-8都是可以的,1e-10就不可以了。而long double 1e-6~1e-12均可以。原因嘛,double精确位数一般14位,而这题答案不超过1e5(题目不给坐标范围,是拿ac程序试出来的),于是。。
精度PS2:这题如果二分上界过大就会丢失精度。有两种方法处理。way1:分离弧面积(有一个mid*mid在那里)和三角形面积;way2:使用way1基础上避免acos。这样way2的二分上界至少可以开到1e10,而way1就不可以,而且way的1eps使用1e-8就会wa
//way1
#define N 155
Point a[N],aa[N];
d_ rr;
vector<Point> re;
bool ok(d_ mid)
{ d_ tot,ar,ar2=0;
tot=ar=pi;
Point y(0,0);
Circle c(y,mid);
fr(i,0,n-1)
{ re.clear();
Line l=Line(a[i],a[i+1]-a[i]);d_ t1,t2;
int t=get_Line_Circle_intersection(l,c,t1,t2,re);
if (t<2)continue;
if (on_segment(a[i+1],re[0],a[i])&&on_segment(a[i+1],re[1],a[i]))continue;//!
if (on_segment(a[i],re[0],a[i+1])&&on_segment(a[i],re[1],a[i+1]))continue;//!
for (int x=0;x<=1;x++)
{
if (on_segment(re[x],a[i],a[i+1])||re[x]==a[i]||re[x]==a[i+1]);
else if (dist(re[x],a[i])>dist(re[x],a[i+1]))
{
ar2-=fabs(area2(y,re[x],a[i+1]))/2;
d_ tt=angle(re[x],a[i+1]);
ar+=tt/2;
}
else{
ar2-=fabs(area2(y,re[x],a[i]))/2;
d_ tt=angle(re[x],a[i]);
ar+=tt/2;
}
}
d_ tt=angle(re[0],re[1]);
ar-=tt/2;
ar2+=fabs(area2(y,re[0],re[1]))/2;
}
if (fabs(ar)>eps)ar2+=ar*mid*mid;
return dcmp(ar2-rr)>=0;
}
void doit()
{ scanf("%lf",&rr);
d_ l=0,r=1e7,mid;
Point y=Point(0,0);
fr(i,0,n-1) aa[i].read();
n=convex(aa,n,a);
fr(i,n,n+n-1) a[i]=a[i-n];
while (r-l>=1e-4)
{
mid=(r+l)/2;
if (ok(mid))r=mid;else l=mid;
}
printf("%.2lf\n",r);
}
int main()
{ int id=0;
while (scanf("%d",&n),n){printf("Case %d: ",++id); doit();}
}
//way2
#define N 155
Point a[N],aa[N];
d_ rr,maxdist,zer;
vector<Point> re;
bool ok(d_ mid)
{ d_ arc=1,ars=0,ar2=0,nc,ns,mc,ms;
Point y(zer,zer);
Circle c(y,mid);
fr(i,0,n-1)
{ re.clear();
Line l=Line(a[i],a[i+1]-a[i]);d_ t1,t2;
int t=get_Line_Circle_intersection(l,c,t1,t2,re)
if (t<2)continue;
if (on_segment(a[i+1],re[0],a[i])&&on_segment(a[i+1],re[1],a[i]))continue;
if (on_segment(a[i],re[0],a[i+1])&&on_segment(a[i],re[1],a[i+1]))continue;
for (int x=0;x<=1;x++)
{
if (on_segment(re[x],a[i],a[i+1])||re[x]==a[i]||re[x]==a[i+1]);
else if (dist(re[x],a[i])>dist(re[x],a[i+1]))
{ ar2-=fabs(area2(y,re[x],a[i+1]))/2;
nc=anglecos(re[x],a[i+1]);ns=anglesin(re[x],a[i+1]);
ms=ars*nc+arc*ns;mc=arc*nc-ars*ns;
ars=ms;arc=mc;
}
else{
ar2-=fabs(area2(y,re[x],a[i]))/2;
nc=anglecos(re[x],a[i]);ns=anglesin(re[x],a[i]);
ms=ars*nc+arc*ns;
mc=arc*nc-ars*ns;
ars=ms;
arc=mc;
}
}
nc=anglecos(re[0],re[1]);ns=anglesin(re[0],re[1]);
ms=ars*nc-arc*ns;
mc=arc*nc+ars*ns;
ars=ms;
arc=mc;
ar2+=fabs(area2(y,re[0],re[1]))/2;
}
Vector vv=Vector(arc,ars);
d_ ar=atan2(vv.y,vv.x);
if (fabs(ar)<eps)
{
if (dcmp(mid-maxdist)<=0)ar=2*pi;else ar=0;
}
else ar=ensure_angle(ar);
ar/=2;
ar2+=ar*mid*mid;
return dcmp(ar2-rr)>=0;
}
void doit()
{ scanf("%Lf",&rr);
d_ l=0,r=1e5,mid;
Point y=Point(zer,zer);
fr(i,0,n-1) aa[i].read();
n=convex(aa,n,a);
fr(i,n,n+n-1) a[i]=a[i-n];
maxdist=1e5;fr(i,0,n-1) {maxdist=min(maxdist,distance_to_Line(y,a[i],a[i+1]));}
while (r-l>=1e-6)
{
mid=(r+l)/2;
if (ok(mid))r=mid;else l=mid;
}
printf("%.2Lf\n",r);
}
int main()
{ int id=0;
zer=0;
while (scanf("%d",&n),n){printf("Case %d: ",++id); doit();}
}